Repository: lovesunstar/stkitdemo Branch: master Commit: a844ecad995f Files: 341 Total size: 42.0 MB Directory structure: gitextract_9zbrd07j/ ├── .gitignore ├── README.md ├── STKitDemo/ │ ├── Classes/ │ │ ├── 3rdLibs/ │ │ │ ├── MZCroppableView/ │ │ │ │ ├── MZCroppableView.h │ │ │ │ ├── MZCroppableView.m │ │ │ │ ├── UIBezierPath-Points.h │ │ │ │ └── UIBezierPath-Points.m │ │ │ ├── PingTester/ │ │ │ │ ├── SimplePing.h │ │ │ │ └── SimplePing.m │ │ │ └── SphereView/ │ │ │ ├── PFGoldenSectionSpiral.h │ │ │ ├── PFGoldenSectionSpiral.m │ │ │ ├── ZYQSphereView.h │ │ │ └── ZYQSphereView.m │ │ ├── BaseUI/ │ │ │ ├── STAlertView.h │ │ │ ├── STAlertView.m │ │ │ ├── STDCardTransitionDelegate.h │ │ │ ├── STDCardTransitionDelegate.m │ │ │ ├── STDCoreDataManager.h │ │ │ ├── STDCoreDataManager.m │ │ │ ├── STDLoadingView.h │ │ │ ├── STDLoadingView.m │ │ │ ├── STDRefreshControl.h │ │ │ ├── STDRefreshControl.m │ │ │ ├── STDRotateTransitionDelegate.h │ │ │ ├── STDRotateTransitionDelegate.m │ │ │ ├── STDScrollViewController.h │ │ │ ├── STDScrollViewController.m │ │ │ ├── STDTabBarController.h │ │ │ ├── STDTabBarController.m │ │ │ ├── STDTableViewController.h │ │ │ ├── STDTableViewController.m │ │ │ ├── STDTextTableViewController.h │ │ │ ├── STDTextTableViewController.m │ │ │ ├── STDTransitionDelegate.h │ │ │ ├── STDTransitionDelegate.m │ │ │ ├── STDViewController.h │ │ │ ├── STDViewController.m │ │ │ ├── STDropMenuView.h │ │ │ ├── STDropMenuView.m │ │ │ ├── STMenuView.h │ │ │ ├── STMenuView.m │ │ │ └── SideBar/ │ │ │ ├── STDLeftViewController.h │ │ │ ├── STDLeftViewController.m │ │ │ ├── STDSideBarController.h │ │ │ └── STDSideBarController.m │ │ ├── Modules/ │ │ │ ├── Components/ │ │ │ │ ├── Image/ │ │ │ │ │ ├── STDCardViewController.h │ │ │ │ │ ├── STDCardViewController.m │ │ │ │ │ ├── STDFeedCell.h │ │ │ │ │ ├── STDFeedCell.m │ │ │ │ │ ├── STDFeedImageView.h │ │ │ │ │ ├── STDFeedImageView.m │ │ │ │ │ ├── STDFeedItem.h │ │ │ │ │ ├── STDFeedItem.m │ │ │ │ │ ├── STDFeedViewController.h │ │ │ │ │ ├── STDFeedViewController.m │ │ │ │ │ ├── STDownloadViewController.h │ │ │ │ │ └── STDownloadViewController.m │ │ │ │ ├── STDImageBlurViewController.h │ │ │ │ ├── STDImageBlurViewController.m │ │ │ │ ├── STDNavigationTestViewController.h │ │ │ │ ├── STDNavigationTestViewController.m │ │ │ │ ├── STDScrollViewController.h │ │ │ │ ├── STDScrollViewController.m │ │ │ │ ├── STDemoViewController.h │ │ │ │ ├── STDemoViewController.m │ │ │ │ └── TextLayout/ │ │ │ │ ├── STDAboutViewController.h │ │ │ │ ├── STDAboutViewController.m │ │ │ │ ├── STDLinkViewController.h │ │ │ │ ├── STDLinkViewController.m │ │ │ │ ├── STDTextViewController.h │ │ │ │ └── STDTextViewController.m │ │ │ ├── DesignPatterns/ │ │ │ │ ├── Creational/ │ │ │ │ │ ├── STDAbstractFactory.h │ │ │ │ │ ├── STDAbstractFactory.m │ │ │ │ │ ├── STDBuilder.h │ │ │ │ │ ├── STDBuilder.m │ │ │ │ │ ├── STDFactoryMethod.h │ │ │ │ │ ├── STDFactoryMethod.m │ │ │ │ │ ├── STDPrototype.h │ │ │ │ │ ├── STDPrototype.m │ │ │ │ │ ├── STDSingleton.h │ │ │ │ │ └── STDSingleton.m │ │ │ │ ├── STDesignPatterns.h │ │ │ │ └── Structural/ │ │ │ │ ├── STDAdapter.h │ │ │ │ ├── STDAdapter.m │ │ │ │ ├── STDBridge.h │ │ │ │ ├── STDBridge.m │ │ │ │ ├── STDFacade.h │ │ │ │ ├── STDFacade.m │ │ │ │ ├── STDProxy.h │ │ │ │ └── STDProxy.m │ │ │ ├── STDSideBar/ │ │ │ │ ├── STDMapViewController.h │ │ │ │ ├── STDMapViewController.m │ │ │ │ └── STDMapViewController.xib │ │ │ ├── STDStartViewController.h │ │ │ ├── STDStartViewController.m │ │ │ ├── Services/ │ │ │ │ ├── Algorithm/ │ │ │ │ │ ├── STACodeViewController.h │ │ │ │ │ ├── STACodeViewController.m │ │ │ │ │ ├── STAHanoiOperation.h │ │ │ │ │ ├── STAHanoiOperation.m │ │ │ │ │ ├── STAHanoiView.h │ │ │ │ │ ├── STAHanoiView.m │ │ │ │ │ ├── STAHanoiViewController.h │ │ │ │ │ ├── STAHanoiViewController.m │ │ │ │ │ ├── STARootViewController.h │ │ │ │ │ ├── STARootViewController.m │ │ │ │ │ ├── STASortDefines.h │ │ │ │ │ ├── STASortOperation.h │ │ │ │ │ ├── STASortOperation.m │ │ │ │ │ ├── STASortView.h │ │ │ │ │ ├── STASortView.m │ │ │ │ │ ├── STASortViewController.h │ │ │ │ │ └── STASortViewController.m │ │ │ │ ├── BookReader/ │ │ │ │ │ ├── STDBookViewController.h │ │ │ │ │ ├── STDBookViewController.m │ │ │ │ │ ├── STDReaderViewController.h │ │ │ │ │ ├── STDReaderViewController.m │ │ │ │ │ ├── STRichView.h │ │ │ │ │ ├── STRichView.m │ │ │ │ │ └── book.txt │ │ │ │ ├── CoreData/ │ │ │ │ │ ├── Entity/ │ │ │ │ │ │ ├── STDEntityDefines.h │ │ │ │ │ │ ├── STDImage.h │ │ │ │ │ │ ├── STDImage.m │ │ │ │ │ │ ├── STDMessage.h │ │ │ │ │ │ ├── STDMessage.m │ │ │ │ │ │ ├── STDSession.h │ │ │ │ │ │ ├── STDSession.m │ │ │ │ │ │ ├── STDUser.h │ │ │ │ │ │ └── STDUser.m │ │ │ │ │ ├── STDBaseChatCell.h │ │ │ │ │ ├── STDBaseChatCell.m │ │ │ │ │ ├── STDChat.h │ │ │ │ │ ├── STDChat.m │ │ │ │ │ ├── STDChatInputView.h │ │ │ │ │ ├── STDChatInputView.m │ │ │ │ │ ├── STDChatViewController.h │ │ │ │ │ ├── STDChatViewController.m │ │ │ │ │ ├── STDImageChatCell.h │ │ │ │ │ ├── STDImageChatCell.m │ │ │ │ │ ├── STDModel.xcdatamodeld/ │ │ │ │ │ │ ├── .xccurrentversion │ │ │ │ │ │ ├── STDModel 2.xcdatamodel/ │ │ │ │ │ │ │ └── contents │ │ │ │ │ │ └── STDModel.xcdatamodel/ │ │ │ │ │ │ └── contents │ │ │ │ │ ├── STDTextChatCell.h │ │ │ │ │ └── STDTextChatCell.m │ │ │ │ ├── Recorder/ │ │ │ │ │ ├── SCSiriWaveformView.h │ │ │ │ │ ├── SCSiriWaveformView.m │ │ │ │ │ ├── STDAboutAudioViewController.h │ │ │ │ │ ├── STDAboutAudioViewController.m │ │ │ │ │ ├── STDRecordViewController.h │ │ │ │ │ ├── STDRecordViewController.m │ │ │ │ │ ├── STWaveBarView.h │ │ │ │ │ └── STWaveBarView.m │ │ │ │ ├── STDServiceViewController.h │ │ │ │ └── STDServiceViewController.m │ │ │ └── Settings/ │ │ │ ├── Debug/ │ │ │ │ ├── STDAuthorization.h │ │ │ │ ├── STDAuthorization.m │ │ │ │ ├── STDDebugPingViewController.h │ │ │ │ ├── STDDebugPingViewController.m │ │ │ │ ├── STDLocationPickerController.h │ │ │ │ ├── STDLocationPickerController.m │ │ │ │ ├── STDPingServices.h │ │ │ │ ├── STDPingServices.m │ │ │ │ ├── STDebugFoundation.h │ │ │ │ └── STDebugFoundation.m │ │ │ ├── STDButton.h │ │ │ ├── STDButton.m │ │ │ ├── STDFontViewController.h │ │ │ ├── STDFontViewController.m │ │ │ ├── STDMoreViewController.h │ │ │ ├── STDMoreViewController.m │ │ │ ├── STDNavigationSettingViewController.h │ │ │ ├── STDNavigationSettingViewController.m │ │ │ ├── STDNavigationSettingViewController.xib │ │ │ ├── STDSettingViewController.h │ │ │ └── STDSettingViewController.m │ │ └── STKit.framework/ │ │ ├── Headers/ │ │ │ ├── Foundation+STKit.h │ │ │ ├── NSData+STGZip.h │ │ │ ├── STAESCryptor.h │ │ │ ├── STAlbumManager.h │ │ │ ├── STApplicationContext.h │ │ │ ├── STAudioCenter.h │ │ │ ├── STAudioRecorder.h │ │ │ ├── STButton.h │ │ │ ├── STCategories.h │ │ │ ├── STCollectionViewFlowLayout.h │ │ │ ├── STControlDefines.h │ │ │ ├── STCoreDataManager.h │ │ │ ├── STDefines.h │ │ │ ├── STGIFGenerator.h │ │ │ ├── STHTTPConfiguration.h │ │ │ ├── STHTTPNetwork.h │ │ │ ├── STHTTPOperation.h │ │ │ ├── STHTTPRequest.h │ │ │ ├── STImage.h │ │ │ ├── STImageCache.h │ │ │ ├── STImageCollectionView.h │ │ │ ├── STImageLoader.h │ │ │ ├── STImagePickerController.h │ │ │ ├── STImagePresent.h │ │ │ ├── STImageScrollView.h │ │ │ ├── STImageView.h │ │ │ ├── STImageViewController.h │ │ │ ├── STIndicatorView.h │ │ │ ├── STJavaScriptBridge.h │ │ │ ├── STKeychain.h │ │ │ ├── STKit.h │ │ │ ├── STLabel.h │ │ │ ├── STLinkLabel.h │ │ │ ├── STLocationManager.h │ │ │ ├── STModel.h │ │ │ ├── STModelViewController.h │ │ │ ├── STNavigationBar.h │ │ │ ├── STNavigationController.h │ │ │ ├── STNetworkConfiguration.h │ │ │ ├── STNotificationWindow.h │ │ │ ├── STObject.h │ │ │ ├── STPaginationControl.h │ │ │ ├── STPayManager.h │ │ │ ├── STPayViewController.h │ │ │ ├── STPersistence.h │ │ │ ├── STPopoverView.h │ │ │ ├── STRSACryptor.h │ │ │ ├── STRateControl.h │ │ │ ├── STReachability.h │ │ │ ├── STRefreshControl.h │ │ │ ├── STRoundProgressView.h │ │ │ ├── STScrollDirector.h │ │ │ ├── STSearchBar.h │ │ │ ├── STSearchDisplayController.h │ │ │ ├── STShadow.h │ │ │ ├── STSideBarController.h │ │ │ ├── STStringTokenizer.h │ │ │ ├── STTabBar.h │ │ │ ├── STTabBarController.h │ │ │ ├── STTabBarItem.h │ │ │ ├── STTableView.h │ │ │ ├── STTableViewCell.h │ │ │ ├── STTableViewController.h │ │ │ ├── STTextView.h │ │ │ ├── STTheme.h │ │ │ ├── STThemeManager.h │ │ │ ├── STTrashManager.h │ │ │ ├── STURLCache.h │ │ │ ├── STViewController.h │ │ │ ├── STWaveAnalysis.h │ │ │ ├── STWebViewController.h │ │ │ ├── STZipArchive.h │ │ │ ├── UIAlertView+STBlock.h │ │ │ ├── UIImageView+STImageLoader.h │ │ │ ├── UIKit+STKit.h │ │ │ ├── UIView+STConstraint.h │ │ │ └── fft.h │ │ ├── Info.plist │ │ └── STKit │ ├── LaunchScreen.xib │ ├── Main.storyboard │ ├── Resources/ │ │ └── licenses.html │ ├── STDAppDelegate.h │ ├── STDAppDelegate.m │ ├── STDemoImages.xcassets/ │ │ ├── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base/ │ │ │ ├── avatar72.imageset/ │ │ │ │ └── Contents.json │ │ │ └── navigation.imageset/ │ │ │ └── Contents.json │ │ ├── Chat/ │ │ │ ├── bubble_image_green.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bubble_image_white.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bubble_text_green.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── bubble_text_white.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── chat_input_send_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ └── chat_input_send_normal.imageset/ │ │ │ └── Contents.json │ │ ├── FeedCell/ │ │ │ ├── feed_cell_background.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── feed_cell_border.imageset/ │ │ │ │ └── Contents.json │ │ │ └── feed_hot_icon.imageset/ │ │ │ └── Contents.json │ │ ├── LaunchImage.launchimage/ │ │ │ └── Contents.json │ │ ├── Navigation/ │ │ │ ├── nav_cancel_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── nav_done_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── nav_menu_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── nav_refresh_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ └── nav_setting_normal.imageset/ │ │ │ └── Contents.json │ │ ├── Porn/ │ │ │ ├── article_collect.imageset/ │ │ │ │ └── Contents.json │ │ │ └── article_collected.imageset/ │ │ │ └── Contents.json │ │ ├── Publish/ │ │ │ ├── choose_image_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── choose_image_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── hud_done.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── product_default.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish_button_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── publish_button_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ └── publish_tool_bkg.imageset/ │ │ │ └── Contents.json │ │ ├── SearchBar/ │ │ │ ├── search_cancel_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── search_cancel_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── searchbar_bkg.imageset/ │ │ │ │ └── Contents.json │ │ │ └── textfield_delete_normal.imageset/ │ │ │ └── Contents.json │ │ ├── SideBar/ │ │ │ ├── SideBarAvatar_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarAvatar_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarNearby_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarNearby_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarSetting_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarSetting_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── SideBarShare_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ └── SideBarShare_normal.imageset/ │ │ │ └── Contents.json │ │ ├── TabBar/ │ │ │ ├── tab_bkg.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_message_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_message_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_profile_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_profile_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_receipt_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_receipt_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── tab_service_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ └── tab_service_normal.imageset/ │ │ │ └── Contents.json │ │ ├── Test/ │ │ │ ├── button_bkg_highlighted.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── button_bkg_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── home_search_left_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── home_search_right_normal.imageset/ │ │ │ │ └── Contents.json │ │ │ └── search_history_edit.imageset/ │ │ │ └── Contents.json │ │ ├── UIControls/ │ │ │ ├── Menu/ │ │ │ │ ├── wormhole0.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── wormhole1.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── wormhole2.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── wormhole3.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── wormhole4.imageset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── wormhole5.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── aero_button.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── viewer_zoom_in.imageset/ │ │ │ │ └── Contents.json │ │ │ └── viewer_zoom_out.imageset/ │ │ │ └── Contents.json │ │ ├── ViewController/ │ │ │ ├── left_account_header.imageset/ │ │ │ │ └── Contents.json │ │ │ └── left_bkg.imageset/ │ │ │ └── Contents.json │ │ └── terms.imageset/ │ │ └── Contents.json │ ├── STKitDemo-Info.plist │ ├── STKitDemo-Prefix.pch │ ├── STKitDemo.entitlements │ ├── STKitDemoInHouse-Info.plist │ ├── Settings.bundle/ │ │ ├── Root.plist │ │ └── en.lproj/ │ │ └── Root.strings │ ├── en.lproj/ │ │ └── InfoPlist.strings │ └── main.m ├── STKitDemo.xcodeproj/ │ └── project.pbxproj ├── STKitDemoTests/ │ ├── DesignPatterns/ │ │ └── Creational/ │ │ ├── STDAbstractFactoryTests.m │ │ ├── STDFactoryMethodTests.m │ │ └── STDSingletonTests.m │ ├── Info.plist │ └── STKitDemoTests.m └── STKitWidget/ ├── Info.plist ├── MainInterface.storyboard ├── STKitWidgetInHouse-Info.plist ├── TodayViewController.h └── TodayViewController.m ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.DS_Store *.swp *project.xcworkspace *contents.xcworkspacedata *.xcuserdata* *xcuserdata* .DS_Store xcuserdata/ xcshareddata/ ================================================ FILE: README.md ================================================ A demo of the STKit. Download[STKit](https://github.com/lovesunstar/STKit) STKit is a collection of useful classes for iOS Developer,it can help you to simplify the approach to develop your iOS applications saving time and more efficiently. UIKit ```STNavigationController``` (Based on UIViewController) ```STTabBarController``` (Based on UIViewController) ```STSideBarController``` (A container controller) ```STImagePickerController``` (You can select more than one picture) ```STLinkLabel``` (Label contains hyperlink and custom link) ```STImagePresent``` (Preview a list of images with a cool animation) ```UIKit+STKit``` (Some useful categories on uiview) and so on. Foundation ```STObject``` (convert JSON->Model) ```STNetwork``` (a network engine based urlconnection and operation queue) ```STImageDownloader``` (Download and cache image) ```STAESCryptor``` (Crypto using AES) ```STRSACryptor``` (Crypto using RSA, including some common way to exact the public key and the private key) ```Foundation+STKit``` (Categories ) and so on There are many other tools, you can checkout and find them. I will always update stkit. Some knowledge can be found in my blogs. [技术哥的博客](http://suenblog.duapp.com) ================================================ FILE: STKitDemo/Classes/3rdLibs/MZCroppableView/MZCroppableView.h ================================================ // // MZCroppableView.h // MZCroppableView // // Created by macbook on 30/10/2013. // Copyright (c) 2013 macbook. All rights reserved. // #import @interface MZCroppableView : UIView { } @property(nonatomic, strong) UIBezierPath *croppingPath; @property(nonatomic, strong) UIColor *lineColor; @property(nonatomic, assign) float lineWidth; - (id)initWithImageView:(UIImageView *)imageView; + (CGPoint)convertCGPoint:(CGPoint)point1 fromRect1:(CGSize)rect1 toRect2:(CGSize)rect2; + (CGPoint)convertPoint:(CGPoint)point1 fromRect1:(CGSize)rect1 toRect2:(CGSize)rect2; + (CGRect)scaleRespectAspectFromRect1:(CGRect)rect1 toRect2:(CGRect)rect2; - (UIImage *)deleteBackgroundOfImage:(UIImageView *)image; @end ================================================ FILE: STKitDemo/Classes/3rdLibs/MZCroppableView/MZCroppableView.m ================================================ // // MZCroppableView.m // MZCroppableView // // Created by macbook on 30/10/2013. // Copyright (c) 2013 macbook. All rights reserved. // #import "MZCroppableView.h" #import "UIBezierPath-Points.h" @implementation MZCroppableView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } - (id)initWithImageView:(UIImageView *)imageView { self = [super initWithFrame:imageView.frame]; if (self) { self.lineWidth = 2.0f; [self setBackgroundColor:[UIColor clearColor]]; [self setClipsToBounds:YES]; [self setUserInteractionEnabled:YES]; self.croppingPath = [[UIBezierPath alloc] init]; [self.croppingPath setLineWidth:self.lineWidth]; self.lineColor = [UIColor colorWithRed:0xFF/255. green:0x73/255. blue:0 alpha:1.]; } return self; } #pragma mark - My Methods - + (CGRect)scaleRespectAspectFromRect1:(CGRect)rect1 toRect2:(CGRect)rect2 { CGSize scaledSize = rect2.size; float scaleFactor = 1.0; CGFloat widthFactor = rect2.size.width / rect1.size.width; CGFloat heightFactor = rect2.size.height / rect1.size.width; if (widthFactor < heightFactor) scaleFactor = widthFactor; else scaleFactor = heightFactor; scaledSize.height = rect1.size.height *scaleFactor; scaledSize.width = rect1.size.width *scaleFactor; float y = (rect2.size.height - scaledSize.height)/2; return CGRectMake(0, y, scaledSize.width, scaledSize.height); } + (CGPoint)convertCGPoint:(CGPoint)point1 fromRect1:(CGSize)rect1 toRect2:(CGSize)rect2 { point1.y = rect1.height - point1.y; CGPoint result = CGPointMake((point1.x*rect2.width)/rect1.width, (point1.y*rect2.height)/rect1.height); return result; } + (CGPoint)convertPoint:(CGPoint)point1 fromRect1:(CGSize)rect1 toRect2:(CGSize)rect2 { CGPoint result = CGPointMake((point1.x*rect2.width)/rect1.width, (point1.y*rect2.height)/rect1.height); return result; } - (void)drawRect:(CGRect)rect { // Drawing code [self.lineColor setStroke]; [self.croppingPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0f]; } - (UIImage *)deleteBackgroundOfImage:(UIImageView *)image { NSArray *points = [self.croppingPath points]; CGRect rect = CGRectZero; rect.size = image.image.size; UIBezierPath *aPath; UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0); { [[UIColor blackColor] setFill]; UIRectFill(rect); [[UIColor whiteColor] setFill]; aPath = [UIBezierPath bezierPath]; // Set the starting point of the shape. CGPoint point = ([points[0] isKindOfClass:[NSString class]]) ? CGPointFromString(points[0]) : [points[0] CGPointValue]; CGPoint p1 = [MZCroppableView convertCGPoint:point fromRect1:image.frame.size toRect2:image.image.size]; [aPath moveToPoint:CGPointMake(p1.x, p1.y)]; for (uint i=1; i @interface UIBezierPath (Points) @property (nonatomic, readonly) NSArray *points; @property (nonatomic, readonly) NSArray *bezierElements; @property (nonatomic, readonly) CGFloat length; - (NSArray *) pointPercentArray; - (CGPoint) pointAtPercent: (CGFloat) percent withSlope: (CGPoint *) slope; + (UIBezierPath *) pathWithPoints: (NSArray *) points; + (UIBezierPath *) pathWithElements: (NSArray *) elements; @end ================================================ FILE: STKitDemo/Classes/3rdLibs/MZCroppableView/UIBezierPath-Points.m ================================================ /* Erica Sadun, http://ericasadun.com iPhone Developer's Cookbook, 6.x Edition BSD License, Use at your own risk */ #import "UIBezierPath-Points.h" #define POINTSTRING(_CGPOINT_) (NSStringFromCGPoint(_CGPOINT_)) #define VALUE(_INDEX_) NSStringFromCGPoint(points[_INDEX_]) #define POINT(_INDEX_) CGPointFromString(points[_INDEX_]) // Return distance between two points static CGFloat distance (CGPoint p1, CGPoint p2) { CGFloat dx = p2.x - p1.x; CGFloat dy = p2.y - p1.y; return sqrt(dx*dx + dy*dy); } @implementation UIBezierPath (Points) void getPointsFromBezier(void *info, const CGPathElement *element) { NSMutableArray *bezierPoints = (__bridge NSMutableArray *)info; CGPathElementType type = element->type; CGPoint *points = element->points; if (type != kCGPathElementCloseSubpath) { if ((type == kCGPathElementAddLineToPoint) || (type == kCGPathElementMoveToPoint)) [bezierPoints addObject:VALUE(0)]; else if (type == kCGPathElementAddQuadCurveToPoint) [bezierPoints addObject:VALUE(1)]; else if (type == kCGPathElementAddCurveToPoint) [bezierPoints addObject:VALUE(2)]; } } - (NSArray *)points { NSMutableArray *points = [NSMutableArray array]; CGPathApply(self.CGPath, (__bridge void *)points, getPointsFromBezier); return points; } // Return a Bezier path buit with the supplied points + (UIBezierPath *) pathWithPoints: (NSArray *) points { UIBezierPath *path = [UIBezierPath bezierPath]; if (points.count == 0) return path; [path moveToPoint:POINT(0)]; for (int i = 1; i < points.count; i++) [path addLineToPoint:POINT(i)]; return path; } - (CGFloat) length { NSArray *points = self.points; float totalPointLength = 0.0f; for (int i = 1; i < points.count; i++) totalPointLength += distance(POINT(i), POINT(i-1)); return totalPointLength; } - (NSArray *) pointPercentArray { // Use total length to calculate the percent of path consumed at each control point NSArray *points = self.points; NSInteger pointCount = points.count; CGFloat totalPointLength = self.length; CGFloat distanceTravelled = 0.0f; NSMutableArray *pointPercentArray = [NSMutableArray array]; [pointPercentArray addObject:@(0.0f)]; for (int i = 1; i < pointCount; i++) { distanceTravelled += distance(POINT(i), POINT(i-1)); [pointPercentArray addObject:@(distanceTravelled / totalPointLength)]; } // Add a final item just to stop with. Probably not needed. [pointPercentArray addObject:@1.1f]; // 110% return pointPercentArray; } - (CGPoint) pointAtPercent: (CGFloat) percent withSlope: (CGPoint *) slope { NSArray *points = self.points; NSArray *percentArray = self.pointPercentArray; CFIndex lastPointIndex = points.count - 1; if (!points.count) return CGPointZero; // Check for 0% and 100% if (percent <= 0.0f) return POINT(0); if (percent >= 1.0f) return POINT(lastPointIndex); // Find a corresponding pair of points in the path CFIndex index = 1; while ((index < percentArray.count) && (percent > ((NSNumber *)percentArray[index]).floatValue)) index++; // This should not happen. if (index > lastPointIndex) return POINT(lastPointIndex); // Calculate the intermediate distance between the two points CGPoint point1 = POINT(index -1); CGPoint point2 = POINT(index); CGFloat percent1 = [[percentArray objectAtIndex:index - 1] floatValue]; CGFloat percent2 = [[percentArray objectAtIndex:index] floatValue]; CGFloat percentOffset = (percent - percent1) / (percent2 - percent1); CGFloat dx = point2.x - point1.x; CGFloat dy = point2.y - point1.y; // Store dy, dx for retrieving arctan if (slope) *slope = CGPointMake(dx, dy); // Calculate new point CGFloat newX = point1.x + (percentOffset * dx); CGFloat newY = point1.y + (percentOffset * dy); CGPoint targetPoint = CGPointMake(newX, newY); return targetPoint; } void getBezierElements(void *info, const CGPathElement *element) { NSMutableArray *bezierElements = (__bridge NSMutableArray *)info; CGPathElementType type = element->type; CGPoint *points = element->points; switch (type) { case kCGPathElementCloseSubpath: [bezierElements addObject:@[@(type)]]; break; case kCGPathElementMoveToPoint: case kCGPathElementAddLineToPoint: [bezierElements addObject:@[@(type), VALUE(0)]]; break; case kCGPathElementAddQuadCurveToPoint: [bezierElements addObject:@[@(type), VALUE(0), VALUE(1)]]; break; case kCGPathElementAddCurveToPoint: [bezierElements addObject:@[@(type), VALUE(0), VALUE(1), VALUE(2)]]; break; } } - (NSArray *) bezierElements { NSMutableArray *elements = [NSMutableArray array]; CGPathApply(self.CGPath, (__bridge void *)elements, getBezierElements); return elements; } + (UIBezierPath *) pathWithElements: (NSArray *) elements { UIBezierPath *path = [UIBezierPath bezierPath]; if (elements.count == 0) return path; for (NSArray *points in elements) { if (!points.count) continue; CGPathElementType elementType = (CGPathElementType)[points[0] integerValue]; switch (elementType) { case kCGPathElementCloseSubpath: [path closePath]; break; case kCGPathElementMoveToPoint: if (points.count == 2) [path moveToPoint:POINT(1)]; break; case kCGPathElementAddLineToPoint: if (points.count == 2) [path addLineToPoint:POINT(1)]; break; case kCGPathElementAddQuadCurveToPoint: if (points.count == 3) [path addQuadCurveToPoint:POINT(2) controlPoint:POINT(1)]; break; case kCGPathElementAddCurveToPoint: if (points.count == 4) [path addCurveToPoint:POINT(3) controlPoint1:POINT(1) controlPoint2:POINT(2)]; break; } } return path; } @end ================================================ FILE: STKitDemo/Classes/3rdLibs/PingTester/SimplePing.h ================================================ /* File: SimplePing.h Contains: Implements ping. Written by: DTS Copyright: Copyright (c) 2010 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import #if TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR #import #else #import #endif #include #pragma mark * SimplePing // The SimplePing class is a very simple class that lets you send and receive pings. #pragma mark * IP and ICMP On-The-Wire Format // The following declarations specify the structure of ping packets on the wire. // IP header structure: struct IPHeader { uint8_t versionAndHeaderLength; uint8_t differentiatedServices; uint16_t totalLength; uint16_t identification; uint16_t flagsAndFragmentOffset; uint8_t timeToLive; uint8_t protocol; uint16_t headerChecksum; uint8_t sourceAddress[4]; uint8_t destinationAddress[4]; // options... // data... }; typedef struct IPHeader IPHeader; // ICMP type and code combinations: enum { kICMPTypeEchoReply = 0, // code is always 0 kICMPTypeEchoRequest = 8 // code is always 0 }; // ICMP header structure: struct ICMPHeader { uint8_t type; uint8_t code; uint16_t checksum; uint16_t identifier; uint16_t sequenceNumber; // data... }; typedef struct ICMPHeader ICMPHeader; @protocol SimplePingDelegate; @interface SimplePing : NSObject { NSString * _hostName; NSData * _hostAddress; CFHostRef _host; CFSocketRef _socket; id _delegate; uint16_t _identifier; // host byte order uint16_t _nextSequenceNumber; // host byte order } + (SimplePing *)simplePingWithHostName:(NSString *)hostName; // chooses first IPv4 address + (SimplePing *)simplePingWithHostAddress:(NSData *)hostAddress; // contains (struct sockaddr) @property (nonatomic, assign, readwrite) id delegate; @property (nonatomic, copy, readonly) NSString * hostName; @property (nonatomic, copy, readonly) NSData * hostAddress; @property (nonatomic, assign, readonly) uint16_t identifier; @property (nonatomic, assign, readonly) uint16_t nextSequenceNumber; @property (nonatomic, copy) NSString *IPAddress; - (void)start; // Starts the pinger object pinging. You should call this after // you've setup the delegate and any ping parameters. - (void)sendPingWithData:(NSData *)data; // Sends an actual ping. Pass nil for data to use a standard 56 byte payload (resulting in a // standard 64 byte ping). Otherwise pass a non-nil value and it will be appended to the // ICMP header. // // Do not try to send a ping before you receive the -simplePing:didStartWithAddress: delegate // callback. - (void)stop; // Stops the pinger object. You should call this when you're done // pinging. + (const struct ICMPHeader *)icmpInPacket:(NSData *)packet; // Given a valid IP packet contains an ICMP , returns the address of the ICMP header that // follows the IP header. This doesn't do any significant validation of the packet. @end @protocol SimplePingDelegate @optional - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address; // Called after the SimplePing has successfully started up. After this callback, you // can start sending pings via -sendPingWithData: - (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error; // If this is called, the SimplePing object has failed. By the time this callback is // called, the object has stopped (that is, you don't need to call -stop yourself). // IMPORTANT: On the send side the packet does not include an IP header. // On the receive side, it does. In that case, use +[SimplePing icmpInPacket:] // to find the ICMP header within the packet. - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet ICMPHeader:(ICMPHeader *)ICMPHeader; // Called whenever the SimplePing object has successfully sent a ping packet. - (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet error:(NSError *)error; // Called whenever the SimplePing object tries and fails to send a ping packet. - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet timeElasped:(NSTimeInterval)timeElasped; // Called whenever the SimplePing object receives an ICMP packet that looks like // a response to one of our pings (that is, has a valid ICMP checksum, has // an identifier that matches our identifier, and has a sequence number in // the range of sequence numbers that we've sent out). - (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet; // Called whenever the SimplePing object receives an ICMP packet that does not // look like a response to one of our pings. @end check_compile_time(sizeof(IPHeader) == 20); check_compile_time(offsetof(IPHeader, versionAndHeaderLength) == 0); check_compile_time(offsetof(IPHeader, differentiatedServices) == 1); check_compile_time(offsetof(IPHeader, totalLength) == 2); check_compile_time(offsetof(IPHeader, identification) == 4); check_compile_time(offsetof(IPHeader, flagsAndFragmentOffset) == 6); check_compile_time(offsetof(IPHeader, timeToLive) == 8); check_compile_time(offsetof(IPHeader, protocol) == 9); check_compile_time(offsetof(IPHeader, headerChecksum) == 10); check_compile_time(offsetof(IPHeader, sourceAddress) == 12); check_compile_time(offsetof(IPHeader, destinationAddress) == 16); check_compile_time(sizeof(ICMPHeader) == 8); check_compile_time(offsetof(ICMPHeader, type) == 0); check_compile_time(offsetof(ICMPHeader, code) == 1); check_compile_time(offsetof(ICMPHeader, checksum) == 2); check_compile_time(offsetof(ICMPHeader, identifier) == 4); check_compile_time(offsetof(ICMPHeader, sequenceNumber) == 6); ================================================ FILE: STKitDemo/Classes/3rdLibs/PingTester/SimplePing.m ================================================ /* File: SimplePing.m Contains: Implements ping. Written by: DTS Copyright: Copyright (c) 2010 Apple Inc. All Rights Reserved. Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. ("Apple") in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software. In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated. The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "SimplePing.h" #include #include #import #pragma mark * ICMP On-The-Wire Format static uint16_t in_cksum(const void *buffer, size_t bufferLen) // This is the standard BSD checksum code, modified to use modern types. { size_t bytesLeft; int32_t sum; const uint16_t * cursor; union { uint16_t us; uint8_t uc[2]; } last; uint16_t answer; bytesLeft = bufferLen; sum = 0; cursor = buffer; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (bytesLeft > 1) { sum += *cursor; cursor += 1; bytesLeft -= 2; } /* mop up an odd byte, if necessary */ if (bytesLeft == 1) { last.uc[0] = * (const uint8_t *) cursor; last.uc[1] = 0; sum += last.us; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return answer; } #pragma mark * SimplePing @interface SimplePing () @property (nonatomic, copy, readwrite) NSData * hostAddress; @property (nonatomic, assign, readwrite) uint16_t nextSequenceNumber; @property (nonatomic, retain) NSDate *pingStartDate; - (void)_stopHostResolution; - (void)_stopDataTransfer; @end @implementation SimplePing - (id)initWithHostName:(NSString *)hostName address:(NSData *)hostAddress // The initialiser common to both of our construction class methods. { assert( (hostName != nil) == (hostAddress == nil) ); self = [super init]; if (self != nil) { self->_hostName = [hostName copy]; self->_hostAddress = [hostAddress copy]; self->_identifier = (uint16_t) arc4random(); } return self; } - (void)dealloc { // -stop takes care of _host and _socket. [self stop]; assert(self->_host == NULL); assert(self->_socket == NULL); [self->_hostName release]; [self->_hostAddress release]; self.IPAddress = nil; [super dealloc]; } + (SimplePing *)simplePingWithHostName:(NSString *)hostName // See comment in header. { return [[[SimplePing alloc] initWithHostName:hostName address:nil] autorelease]; } + (SimplePing *)simplePingWithHostAddress:(NSData *)hostAddress // See comment in header. { return [[[SimplePing alloc] initWithHostName:NULL address:hostAddress] autorelease]; } @synthesize hostName = _hostName; @synthesize hostAddress = _hostAddress; @synthesize delegate = _delegate; @synthesize identifier = _identifier; @synthesize nextSequenceNumber = _nextSequenceNumber; - (void)_didFailWithError:(NSError *)error // Shut down the pinger object and tell the delegate about the error. { assert(error != nil); // We retain ourselves temporarily because it's common for the delegate method // to release its last reference to use, which causes -dealloc to be called here. // If we then reference self on the return path, things go badly. I don't think // that happens currently, but I've got into the habit of doing this as a // defensive measure. [[self retain] autorelease]; [self stop]; if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didFailWithError:)] ) { [self.delegate simplePing:self didFailWithError:error]; } } - (void)_didFailWithHostStreamError:(CFStreamError)streamError // Convert the CFStreamError to an NSError and then call through to // -_didFailWithError: to shut down the pinger object and tell the // delegate about the error. { NSDictionary * userInfo; NSError * error; if (streamError.domain == kCFStreamErrorDomainNetDB) { userInfo = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:streamError.error], kCFGetAddrInfoFailureKey, nil ]; } else { userInfo = nil; } error = [NSError errorWithDomain:(NSString *)kCFErrorDomainCFNetwork code:kCFHostErrorUnknown userInfo:userInfo]; assert(error != nil); [self _didFailWithError:error]; } - (void)sendPingWithData:(NSData *)data // See comment in header. { int err; NSData * payload; NSMutableData * packet; ICMPHeader * icmpPtr; ssize_t bytesSent; // Construct the ping packet. payload = data; if (payload == nil) { payload = [[NSString stringWithFormat:@"%28zd bottles of beer on the wall", (ssize_t) 99 - (size_t) (self.nextSequenceNumber % 100) ] dataUsingEncoding:NSASCIIStringEncoding]; assert(payload != nil); assert([payload length] == 56); } packet = [NSMutableData dataWithLength:sizeof(*icmpPtr) + [payload length]]; assert(packet != nil); icmpPtr = [packet mutableBytes]; icmpPtr->type = kICMPTypeEchoRequest; icmpPtr->code = 0; icmpPtr->checksum = 0; icmpPtr->identifier = OSSwapHostToBigInt16(self.identifier); icmpPtr->sequenceNumber = OSSwapHostToBigInt16(self.nextSequenceNumber); memcpy(&icmpPtr[1], [payload bytes], [payload length]); // The IP checksum returns a 16-bit number that's already in correct byte order // (due to wacky 1's complement maths), so we just put it into the packet as a // 16-bit unit. icmpPtr->checksum = in_cksum([packet bytes], [packet length]); // Send the packet. if (self->_socket == NULL) { bytesSent = -1; err = EBADF; } else { bytesSent = sendto( CFSocketGetNative(self->_socket), [packet bytes], [packet length], 0, (struct sockaddr *) [self.hostAddress bytes], (socklen_t) [self.hostAddress length] ); err = 0; if (bytesSent < 0) { err = errno; } } // Handle the results of the send. self.pingStartDate = nil; if ( (bytesSent > 0) && (((NSUInteger) bytesSent) == [packet length]) ) { self.pingStartDate = [NSDate date]; // Complete success. Tell the client. if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didSendPacket:ICMPHeader:)] ) { [self.delegate simplePing:self didSendPacket:packet ICMPHeader:icmpPtr]; } } else { NSError * error; // Some sort of failure. Tell the client. if (err == 0) { err = ENOBUFS; // This is not a hugely descriptor error, alas. } error = [NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]; if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didFailToSendPacket:error:)] ) { [self.delegate simplePing:self didFailToSendPacket:packet error:error]; } } self.nextSequenceNumber += 1; } + (NSUInteger)_icmpHeaderOffsetInPacket:(NSData *)packet // Returns the offset of the ICMPHeader within an IP packet. { NSUInteger result; const struct IPHeader * ipPtr; size_t ipHeaderLength; result = NSNotFound; if ([packet length] >= (sizeof(IPHeader) + sizeof(ICMPHeader))) { ipPtr = (const IPHeader *) [packet bytes]; assert((ipPtr->versionAndHeaderLength & 0xF0) == 0x40); // IPv4 assert(ipPtr->protocol == 1); // ICMP ipHeaderLength = (ipPtr->versionAndHeaderLength & 0x0F) * sizeof(uint32_t); if ([packet length] >= (ipHeaderLength + sizeof(ICMPHeader))) { result = ipHeaderLength; } } return result; } + (const struct ICMPHeader *)icmpInPacket:(NSData *)packet // See comment in header. { const struct ICMPHeader * result; NSUInteger icmpHeaderOffset; result = nil; icmpHeaderOffset = [self _icmpHeaderOffsetInPacket:packet]; if (icmpHeaderOffset != NSNotFound) { result = (const struct ICMPHeader *) (((const uint8_t *)[packet bytes]) + icmpHeaderOffset); } return result; } - (BOOL)_isValidPingResponsePacket:(NSMutableData *)packet // Returns true if the packet looks like a valid ping response packet destined // for us. { BOOL result; NSUInteger icmpHeaderOffset; ICMPHeader * icmpPtr; uint16_t receivedChecksum; uint16_t calculatedChecksum; result = NO; icmpHeaderOffset = [[self class] _icmpHeaderOffsetInPacket:packet]; if (icmpHeaderOffset != NSNotFound) { icmpPtr = (struct ICMPHeader *) (((uint8_t *)[packet mutableBytes]) + icmpHeaderOffset); receivedChecksum = icmpPtr->checksum; icmpPtr->checksum = 0; calculatedChecksum = in_cksum(icmpPtr, [packet length] - icmpHeaderOffset); icmpPtr->checksum = receivedChecksum; if (receivedChecksum == calculatedChecksum) { if ( (icmpPtr->type == kICMPTypeEchoReply) && (icmpPtr->code == 0) ) { if ( OSSwapBigToHostInt16(icmpPtr->identifier) == self.identifier ) { if ( OSSwapBigToHostInt16(icmpPtr->sequenceNumber) < self.nextSequenceNumber ) { result = YES; } } } } } return result; } - (void)_readData // Called by the socket handling code (SocketReadCallback) to process an ICMP // messages waiting on the socket. { int err; struct sockaddr_storage addr; socklen_t addrLen; ssize_t bytesRead; void * buffer; enum { kBufferSize = 65535 }; // 65535 is the maximum IP packet size, which seems like a reasonable bound // here (plus it's what uses). buffer = malloc(kBufferSize); assert(buffer != NULL); // Actually read the data. addrLen = sizeof(addr); bytesRead = recvfrom(CFSocketGetNative(self->_socket), buffer, kBufferSize, 0, (struct sockaddr *) &addr, &addrLen); err = 0; if (bytesRead < 0) { err = errno; } // Process the data we read. if (bytesRead > 0) { NSMutableData * packet; packet = [NSMutableData dataWithBytes:buffer length:bytesRead]; assert(packet != nil); // We got some data, pass it up to our client. NSTimeInterval timeInterval = 0.0f; if (self.pingStartDate) { timeInterval = [[NSDate date] timeIntervalSinceDate:self.pingStartDate]; } if ( [self _isValidPingResponsePacket:packet] ) { if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didReceivePingResponsePacket:timeElasped:)] ) { [self.delegate simplePing:self didReceivePingResponsePacket:packet timeElasped:timeInterval]; } } else { if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didReceiveUnexpectedPacket:)] ) { [self.delegate simplePing:self didReceiveUnexpectedPacket:packet]; } } } else { // We failed to read the data, so shut everything down. if (err == 0) { err = EPIPE; } [self _didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]]; } self.pingStartDate = nil; free(buffer); // Note that we don't loop back trying to read more data. Rather, we just // let CFSocket call us again. } static void SocketReadCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) // This C routine is called by CFSocket when there's data waiting on our // ICMP socket. It just redirects the call to Objective-C code. { SimplePing * obj; obj = (SimplePing *) info; assert([obj isKindOfClass:[SimplePing class]]); #pragma unused(s) assert(s == obj->_socket); #pragma unused(type) assert(type == kCFSocketReadCallBack); #pragma unused(address) assert(address == nil); #pragma unused(data) assert(data == nil); [obj _readData]; } - (void)_startWithHostAddress // We have a host address, so let's actually start pinging it. { int err; int fd; const struct sockaddr * addrPtr; char ipAddress[INET6_ADDRSTRLEN]; assert(self.hostAddress != nil); // Open the socket. addrPtr = (const struct sockaddr *) [self.hostAddress bytes]; /* getnameinfo coverts an IPv4 or IPv6 address into a text string. */ int eno = getnameinfo(addrPtr, addrPtr->sa_len, ipAddress, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); if (eno == 0) { NSString *IPAddress = [[[NSString alloc] initWithFormat:@"%s",ipAddress] autorelease]; // NSLog(@"%@", IPAddress); self.IPAddress = IPAddress; } fd = -1; err = 0; switch (addrPtr->sa_family) { case AF_INET: { fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); if (fd < 0) { err = errno; } } break; case AF_INET6: assert(NO); // fall through default: { err = EPROTONOSUPPORT; } break; } if (err != 0) { [self _didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]]; } else { CFSocketContext context = {0, self, NULL, NULL, NULL}; CFRunLoopSourceRef rls; // Wrap it in a CFSocket and schedule it on the runloop. self->_socket = CFSocketCreateWithNative(NULL, fd, kCFSocketReadCallBack, SocketReadCallback, &context); assert(self->_socket != NULL); // The socket will now take care of clean up our file descriptor. assert( CFSocketGetSocketFlags(self->_socket) & kCFSocketCloseOnInvalidate ); fd = -1; rls = CFSocketCreateRunLoopSource(NULL, self->_socket, 0); assert(rls != NULL); CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); if ( (self.delegate != nil) && [self.delegate respondsToSelector:@selector(simplePing:didStartWithAddress:)] ) { [self.delegate simplePing:self didStartWithAddress:self.hostAddress]; } } assert(fd == -1); } - (void)_hostResolutionDone // Called by our CFHost resolution callback (HostResolveCallback) when host // resolution is complete. We just latch the first IPv4 address and kick // off the pinging process. { Boolean resolved; NSArray * addresses; char ipAddress[INET6_ADDRSTRLEN]; // Find the first IPv4 address. addresses = (NSArray *)CFHostGetAddressing(self->_host, &resolved); if ( resolved && (addresses != nil) ) { resolved = false; for (NSData * address in addresses) { const struct sockaddr * addrPtr; addrPtr = (const struct sockaddr *) [address bytes]; if ([address length] >= sizeof(struct sockaddr) && addrPtr->sa_family == AF_INET) { self.hostAddress = address; resolved = true; /* getnameinfo coverts an IPv4 or IPv6 address into a text string. */ int err = getnameinfo(addrPtr, addrPtr->sa_len, ipAddress, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); if (err == 0) { NSString *IPAddress = [[[NSString alloc] initWithFormat:@"%s",ipAddress] autorelease]; self.IPAddress = IPAddress; } break; } } } // We're done resolving, so shut that down. [self _stopHostResolution]; // If all is OK, start pinging, otherwise shut down the pinger completely. if (resolved) { [self _startWithHostAddress]; } else { [self _didFailWithError:[NSError errorWithDomain:(NSString *)kCFErrorDomainCFNetwork code:kCFHostErrorHostNotFound userInfo:nil]]; } } static void HostResolveCallback(CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info) // This C routine is called by CFHost when the host resolution is complete. // It just redirects the call to the appropriate Objective-C method. { SimplePing * obj; obj = (SimplePing *) info; assert([obj isKindOfClass:[SimplePing class]]); #pragma unused(theHost) assert(theHost == obj->_host); #pragma unused(typeInfo) assert(typeInfo == kCFHostAddresses); if ( (error != NULL) && (error->domain != 0) ) { [obj _didFailWithHostStreamError:*error]; } else { [obj _hostResolutionDone]; } } - (void)start // See comment in header. { // If the user supplied us with an address, just start pinging that. Otherwise // start a host resolution. if (self->_hostAddress != nil) { [self _startWithHostAddress]; } else { Boolean success; CFHostClientContext context = {0, self, NULL, NULL, NULL}; CFStreamError streamError; assert(self->_host == NULL); self->_host = CFHostCreateWithName(NULL, (CFStringRef) self.hostName); assert(self->_host != NULL); CFHostSetClient(self->_host, HostResolveCallback, &context); CFHostScheduleWithRunLoop(self->_host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); success = CFHostStartInfoResolution(self->_host, kCFHostAddresses, &streamError); if ( ! success ) { [self _didFailWithHostStreamError:streamError]; } } } - (void)_stopHostResolution // Shut down the CFHost. { if (self->_host != NULL) { CFHostSetClient(self->_host, NULL, NULL); CFHostUnscheduleFromRunLoop(self->_host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); CFRelease(self->_host); self->_host = NULL; } } - (void)_stopDataTransfer // Shut down anything to do with sending and receiving pings. { if (self->_socket != NULL) { CFSocketInvalidate(self->_socket); CFRelease(self->_socket); self->_socket = NULL; } } - (void)stop // See comment in header. { [self _stopHostResolution]; [self _stopDataTransfer]; // If we were started with a host name, junk the host address on stop. If the // client calls -start again, we'll re-resolve the host name. if (self.hostName != nil) { self.hostAddress = NULL; } } @end ================================================ FILE: STKitDemo/Classes/3rdLibs/SphereView/PFGoldenSectionSpiral.h ================================================ //This file is part of SphereView. // //SphereView is free software: you can redistribute it and/or modify //it under the terms of the GNU General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. // //SphereView is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with SphereView. If not, see . #import #define PFMatrixMaxSize 4 typedef Float32 STFloat32; struct PFMatrix { NSInteger m; NSInteger n; STFloat32 data[PFMatrixMaxSize][PFMatrixMaxSize]; }; typedef struct PFMatrix PFMatrix; typedef enum { PFAxisDirectionNone, PFAxisDirectionPositive = 1, PFAxisDirectionNegative = -1 } PFAxisDirection; static STFloat32 PFAxisDirectionMinimumDistance = 0.033f; struct PFPoint { STFloat32 x; STFloat32 y; STFloat32 z; }; typedef struct PFPoint PFPoint; @interface PFGoldenSectionSpiral : NSObject { } + (NSArray *)sphere:(NSInteger)n; @end typedef STFloat32 PFRadian; extern PFRadian PFRadianMake(STFloat32 grades); extern PFMatrix PFMatrixTransform3DMakeFromPFPoint(PFPoint point); extern PFMatrix PFMatrixTransform3DMakeTranslation(PFPoint point); extern PFMatrix PFMatrixTransform3DMakeXRotation(PFRadian angle); extern PFMatrix PFMatrixTransform3DMakeXRotationOnPoint(PFPoint point, PFRadian angle); extern PFMatrix PFMatrixTransform3DMakeYRotation(PFRadian angle); extern PFMatrix PFMatrixTransform3DMakeYRotationOnPoint(PFPoint point, PFRadian angle); extern PFMatrix PFMatrixTransform3DMakeZRotation(PFRadian angle); extern PFMatrix PFMatrixTransform3DMakeZRotationOnPoint(PFPoint point, PFRadian angle); extern PFMatrix PFMatrixMake(NSInteger m, NSInteger n); extern PFMatrix PFMatrixMakeFromArray(NSInteger m, NSInteger n, STFloat32 *data); extern PFMatrix PFMatrixMakeIdentity(NSInteger m, NSInteger n); extern PFMatrix PFMatrixMultiply(PFMatrix A, PFMatrix B); extern NSString *NSStringFromPFMatrix(PFMatrix matrix); extern PFPoint PFPointMake(STFloat32 x, STFloat32 y, STFloat32 z); extern PFPoint PFPointMakeFromMatrix(PFMatrix matrix); extern PFPoint PFPointFromString(NSString *string); extern NSString *NSStringFromPFPoint(PFPoint point); extern CGPoint CGPointMakeNormalizedPoint(CGPoint point, STFloat32 distance); extern PFAxisDirection PFAxisDirectionMake(STFloat32 fromCoordinate, STFloat32 toCoordinate, BOOL sensitive); extern PFAxisDirection PFDirectionMakeXAxis(CGPoint fromPoint, CGPoint toPoint); extern PFAxisDirection PFDirectionMakeYAxis(CGPoint fromPoint, CGPoint toPoint); extern PFAxisDirection PFDirectionMakeXAxisSensitive(CGPoint fromPoint, CGPoint toPoint); extern PFAxisDirection PFDirectionMakeYAxisSensitive(CGPoint fromPoint, CGPoint toPoint); ================================================ FILE: STKitDemo/Classes/3rdLibs/SphereView/PFGoldenSectionSpiral.m ================================================ //This file is part of SphereView. // //SphereView is free software: you can redistribute it and/or modify //it under the terms of the GNU General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. // //SphereView is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with SphereView. If not, see . #import "PFGoldenSectionSpiral.h" PFMatrix const PFMatrixZero = {0,0,{{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}}; @implementation PFGoldenSectionSpiral + (NSArray *)sphere:(NSInteger)n { NSMutableArray* result = [NSMutableArray arrayWithCapacity:n]; STFloat32 N = n; STFloat32 inc = M_PI * (3.0f - sqrt(5.0f)); STFloat32 off = 2.0f / N; for (NSInteger k = 0; k < N; k ++) { STFloat32 y = k * off - 1.0f + (off / 2.0f); STFloat32 r = sqrt(1.0f - y*y); STFloat32 phi = k * inc; PFPoint point = PFPointMake(cos(phi)*r, y, sin(phi)*r); [result addObject:NSStringFromPFPoint(point)]; } return result; } @end extern PFRadian PFRadianMake(STFloat32 grades) { return ((STFloat32)(M_PI * grades) / 180.0f); } extern PFMatrix PFMatrixTransform3DMakeFromPFPoint(PFPoint point) { STFloat32 pointRef[1][4] = {{point.x, point.y, point.z, 1.0f}}; PFMatrix matrix = PFMatrixMakeFromArray(1, 4, * pointRef); return matrix; } extern PFMatrix PFMatrixTransform3DMakeTranslation(PFPoint point) { STFloat32 T[4][4] = { {1.0f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {point.x, point.y, point.z, 1.0f} }; PFMatrix matrix = PFMatrixMakeFromArray(4, 4, *T); return matrix; } extern PFMatrix PFMatrixTransform3DMakeXRotation(PFRadian angle) { STFloat32 c = cos(PFRadianMake(angle)); STFloat32 s = sin(PFRadianMake(angle)); STFloat32 T[4][4] = { {1.f, 0.f, 0.f, 0.f}, {0.f, c, s, 0.f}, {0.f, -s, c, 0.f}, {0.f, 0.f, 0.f, 1.f} }; PFMatrix matrix = PFMatrixMakeFromArray(4, 4, *T); return matrix; } extern PFMatrix PFMatrixTransform3DMakeXRotationOnPoint(PFPoint point, PFRadian angle) { PFMatrix T = PFMatrixTransform3DMakeTranslation(PFPointMake(-point.x, -point.y, -point.z)); PFMatrix R = PFMatrixTransform3DMakeXRotation(angle); PFMatrix T1 = PFMatrixTransform3DMakeTranslation(point); return PFMatrixMultiply(PFMatrixMultiply(T, R), T1); } extern PFMatrix PFMatrixTransform3DMakeYRotation(PFRadian angle) { STFloat32 c = cos(PFRadianMake(angle)); STFloat32 s = sin(PFRadianMake(angle)); STFloat32 T[4][4] = { {c, 0, -s, 0}, {0, 1, 0, 0}, {s, 0, c, 0}, {0, 0, 0, 1} }; PFMatrix matrix = PFMatrixMakeFromArray(4, 4, *T); return matrix; } extern PFMatrix PFMatrixTransform3DMakeYRotationOnPoint(PFPoint point, PFRadian angle) { PFMatrix T = PFMatrixTransform3DMakeTranslation(PFPointMake(-point.x, -point.y, -point.z)); PFMatrix R = PFMatrixTransform3DMakeYRotation(angle); PFMatrix T1 = PFMatrixTransform3DMakeTranslation(point); return PFMatrixMultiply(PFMatrixMultiply(T, R), T1); } extern PFMatrix PFMatrixTransform3DMakeZRotation(PFRadian angle) { STFloat32 c = cos(PFRadianMake(angle)); STFloat32 s = sin(PFRadianMake(angle)); STFloat32 T[4][4] = { {c, s, 0.0f, 0.0f}, {-s, c, 0.0f, 0.0f}, {0,0.0f,0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 1.0f} }; PFMatrix matrix = PFMatrixMakeFromArray(4, 4, *T); return matrix; } extern PFMatrix PFMatrixTransform3DMakeZRotationOnPoint(PFPoint point, PFRadian angle) { PFMatrix T = PFMatrixTransform3DMakeTranslation(PFPointMake(-point.x, -point.y, -point.z)); PFMatrix R = PFMatrixTransform3DMakeZRotation(angle); PFMatrix T1 = PFMatrixTransform3DMakeTranslation(point); return PFMatrixMultiply(PFMatrixMultiply(T, R), T1); } extern PFMatrix PFMatrixMake(NSInteger m, NSInteger n) { PFMatrix matrix = PFMatrixZero; matrix.m = m; matrix.n = n; for (NSInteger i = 0; i < m; i ++){ for(NSInteger j = 0; j < n; j ++){ matrix.data[i][j] = (STFloat32)0.0f; } } return matrix; } extern PFMatrix PFMatrixMakeFromArray(NSInteger m, NSInteger n, STFloat32 *data) { PFMatrix matrix = PFMatrixMake(m, n); for (NSInteger i = 0; i < m; i ++) { STFloat32 *t = data+(i*sizeof(STFloat32)); for(NSInteger j = 0; j < n; j++) { matrix.data[i][j] = *(t+j); } } return matrix; } extern PFMatrix PFMatrixMakeIdentity(NSInteger m, NSInteger n) { PFMatrix matrix = PFMatrixMake(m, n); for (NSInteger i = 0; i < m; i++){ matrix.data[i][i] = 1.0f; } return matrix; } extern PFMatrix PFMatrixMultiply(PFMatrix A, PFMatrix B) { PFMatrix R = PFMatrixMake(A.m, B.n); for(NSInteger i = 0; i < A.m; i++){ for(NSInteger j = 0; j < B.n; j++){ for(NSInteger k = 0; k < A.n; k++){ R.data[i][j] += (A.data[i][k] * B.data[k][j]); } } } return R; } extern NSString *NSStringFromPFMatrix(PFMatrix matrix) { NSMutableString *str = [NSMutableString string]; [str appendString:@"{"]; for(NSInteger i=0; i 0) { p.x = [temp[0] floatValue]; } if (temp.count > 1) { p.y = [temp[1] floatValue]; } if (temp.count > 2) { p.z = [temp[2] floatValue]; } return p; } extern NSString *NSStringFromPFPoint(PFPoint point) { return [NSString stringWithFormat:@"%@,%@,%@", @(point.x), @(point.y), @(point.z)]; } #pragma mark - #pragma mark CGPoint methods extern CGPoint CGPointMakeNormalizedPoint(CGPoint point, STFloat32 distance) { return CGPointMake(point.x * 1.0f / distance, point.y * 1.0f / distance); } extern PFAxisDirection PFAxisDirectionMake(STFloat32 fromCoordinate, STFloat32 toCoordinate, BOOL sensitive) { PFAxisDirection direction = PFAxisDirectionNone; STFloat32 distance = fabs(fromCoordinate - toCoordinate); if (distance > PFAxisDirectionMinimumDistance || sensitive) { if (fromCoordinate > toCoordinate) { direction = PFAxisDirectionPositive; } else if (fromCoordinate < toCoordinate) { direction = PFAxisDirectionNegative; } } return direction; } extern PFAxisDirection PFDirectionMakeXAxis(CGPoint fromPoint, CGPoint toPoint) { return PFAxisDirectionMake(fromPoint.x, toPoint.x, NO); } extern PFAxisDirection PFDirectionMakeYAxis(CGPoint fromPoint, CGPoint toPoint) { return PFAxisDirectionMake(fromPoint.y, toPoint.y, NO); } extern PFAxisDirection PFDirectionMakeXAxisSensitive(CGPoint fromPoint, CGPoint toPoint) { return PFAxisDirectionMake(fromPoint.x, toPoint.x, YES); } extern PFAxisDirection PFDirectionMakeYAxisSensitive(CGPoint fromPoint, CGPoint toPoint) { return PFAxisDirectionMake(fromPoint.y, toPoint.y, YES); } ================================================ FILE: STKitDemo/Classes/3rdLibs/SphereView/ZYQSphereView.h ================================================ // // ZYQSphereView.h // SphereViewSample // // Created by Zhao Yiqi on 13-12-8. // Copyright (c) 2013年 Zhao Yiqi. All rights reserved. // #import "PFGoldenSectionSpiral.h" @interface ZYQSphereView : UIView { NSMutableDictionary *pointMap; CGPoint originalLocationInView; CGPoint previousLocationInView; PFAxisDirection lastXAxisDirection; PFAxisDirection lastYAxisDirection; CGRect originalSphereViewBounds; } @property(nonatomic,assign)BOOL isPanTimerStart; @property(nonatomic,getter = isTimerStart,readonly)BOOL isTimerStart; - (void)setItems:(NSArray *)items; -(void)timerStart; -(void)timerStop; @end ================================================ FILE: STKitDemo/Classes/3rdLibs/SphereView/ZYQSphereView.m ================================================ // // ZYQSphereView.m // SphereViewSample // // Created by Zhao Yiqi on 13-12-8. // Copyright (c) 2013年 Zhao Yiqi. All rights reserved. // #import "ZYQSphereView.h" #import @interface ZYQSphereView(Private) - (CGFloat)coordinateForNormalizedValue:(CGFloat)normalizedValue withinRangeOffset:(CGFloat)rangeOffset; - (void)rotateSphereByAngle:(CGFloat)angle fromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint; - (void)layoutViews; - (void)layoutView:(UIView *)view withPoint:(PFPoint)point; @end @interface ZYQSphereView (){ CGFloat intervalX; CGFloat intervalY; } @property(nonatomic,strong)NSTimer *timer; @end @implementation ZYQSphereView -(BOOL)isTimerStart{ return [_timer isValid]; } - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; panRecognizer.minimumNumberOfTouches = 1; [self addGestureRecognizer:panRecognizer]; UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinchGesture:)]; [self addGestureRecognizer:pinchRecognizer]; UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotationGesture:)]; [self addGestureRecognizer:rotationRecognizer]; intervalX = 1.0f; } return self; } -(void)changeView{ CGPoint normalPoint=self.frame.origin; CGPoint movePoint=CGPointMake(self.frame.origin.x+intervalX, self.frame.origin.y+intervalY); [self rotateSphereByAngle:1.0f fromPoint:normalPoint toPoint:movePoint]; } -(void)timerStart{ if (_timer.isValid) { [_timer invalidate]; } self.timer=[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(changeView) userInfo:nil repeats:YES]; } -(void)timerStop{ if (_timer.isValid) { [_timer invalidate]; } } - (void)setItems:(NSArray *)items { pointMap = [[NSMutableDictionary alloc] init]; NSArray *spherePoints = [PFGoldenSectionSpiral sphere:items.count]; for (NSInteger i=0; i screenFrame.size.width && sphereFrame.size.height > screenFrame.size.height) || (sphereFrame.size.width < originalSphereViewBounds.size.width && sphereFrame.size.height < originalSphereViewBounds.size.height)) { return; } view.bounds = sphereFrame; [self layoutViews]; } - (void)handleRotationGesture:(UIRotationGestureRecognizer *)rotationRecognizer { static CGFloat LastSphereRotationAngle; if (rotationRecognizer.state == UIGestureRecognizerStateEnded) { LastSphereRotationAngle = 0; return; } PFAxisDirection rotationDirection; CGFloat rotation = rotationRecognizer.rotation; if (rotation > LastSphereRotationAngle) { rotationDirection = PFAxisDirectionPositive; } else { rotationDirection = PFAxisDirectionNegative; } rotation = fabs(rotation) * rotationDirection; NSArray *subviews = self.subviews; for (NSInteger i = 0; i 0) { coordinate += half; } else { coordinate = half - coordinate; } return coordinate; } - (void)layoutView:(UIView *)view withPoint:(PFPoint)point { CGFloat viewSize = CGRectGetWidth(view.frame); CGFloat width = CGRectGetWidth(self.frame) - viewSize * 2.0f; CGFloat x = [self coordinateForNormalizedValue:point.x withinRangeOffset:width]; CGFloat y = [self coordinateForNormalizedValue:point.y withinRangeOffset:width]; view.center = CGPointMake(x + viewSize, y + viewSize); CGFloat z = [self coordinateForNormalizedValue:point.z withinRangeOffset:1.0f]; view.transform = CGAffineTransformScale(CGAffineTransformIdentity, z, z); view.layer.zPosition = z; } - (void)layoutViews { NSArray *subviews = self.subviews; for (NSInteger i = 0; i < subviews.count; i ++) { UIView *view = [subviews objectAtIndex:i]; NSNumber *key = @(i); PFPoint point = PFPointFromString([pointMap objectForKey:key]); [self layoutView:view withPoint:point]; } } - (void)dealloc { if ([_timer isValid]) { [_timer invalidate]; } } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STAlertView.h ================================================ // // STAlertView.h // STKitDemo // // Created by SunJiangting on 14-8-28. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STAlertView : UIView - (instancetype)initWithMenuTitles:(NSString *)menuTitle, ... NS_REQUIRES_NIL_TERMINATION; - (NSInteger)showInView:(UIView *)view animated:(BOOL)animated; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STAlertView.m ================================================ // // STAlertView.m // STKitDemo // // Created by SunJiangting on 14-8-28. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STAlertView.h" #import @interface _STAlertViewCell : UITableViewCell @property(nonatomic, strong) UILabel *titleLabel; @property(nonatomic, strong) UIView *separatorView; @end const CGFloat _STAlertViewCellHeight = 45; @implementation _STAlertViewCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.frame = CGRectMake(0, 0, 320, _STAlertViewCellHeight); self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 300, 44)]; self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.titleLabel.textColor = [UIColor darkGrayColor]; self.titleLabel.highlightedTextColor = [UIColor whiteColor]; self.titleLabel.font = [UIFont systemFontOfSize:17.]; self.titleLabel.textAlignment = NSTextAlignmentCenter; [self addSubview:self.titleLabel]; self.separatorView = [[UIView alloc] initWithFrame:CGRectZero]; [self addSubview:self.separatorView]; } return self; } - (void)setFrame:(CGRect)frame { [super setFrame:frame]; self.separatorView.frame = CGRectMake(0, CGRectGetHeight(frame) - STOnePixel(), CGRectGetWidth(frame), STOnePixel()); } - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; self.separatorView.backgroundColor = [UIColor colorWithRed:0x99/255. green:0x99/255. blue:0x99/255. alpha:1.0]; } @end @interface STAlertView () { BOOL _shouldContinue; NSInteger _dismissedIndex; } @property(nonatomic, strong) NSMutableArray *dataSource; @property(nonatomic, weak) UITableView *tableView; @property(nonatomic, weak) UIView *backgroundView; @property(nonatomic, weak) UIView *contentView; @property(nonatomic, strong) UIView *hitTestView; @end @implementation STAlertView - (instancetype)initWithMenuTitles:(NSString *)menuTitle, ... NS_REQUIRES_NIL_TERMINATION { NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:1]; NSString *title = nil; va_list args; if (menuTitle) { [dataSource addObject:menuTitle]; va_start(args, menuTitle); while ((title = va_arg(args, NSString *))) { [dataSource addObject:title]; } va_end(args); } self = [super initWithFrame:CGRectZero]; if (self) { self.dataSource = dataSource; CGFloat maxHeight = 240; const CGFloat footerHeight = 1; CGFloat height = dataSource.count * _STAlertViewCellHeight + footerHeight; UIView *backgroundView = [[UIView alloc] initWithFrame:self.bounds]; backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; backgroundView.backgroundColor = [UIColor blackColor]; [self addSubview:backgroundView]; self.backgroundView = backgroundView; UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, STOnePixel(), 0, MIN(height, maxHeight))]; contentView.clipsToBounds = YES; [self addSubview:contentView]; self.contentView = contentView; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissActionFired:)]; tapGesture.numberOfTapsRequired = 1; tapGesture.delegate = self; [self.backgroundView addGestureRecognizer:tapGesture]; UITableView *tableView = [[UITableView alloc] initWithFrame:self.contentView.bounds style:UITableViewStylePlain]; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; tableView.delegate = self; tableView.dataSource = self; tableView.backgroundView = nil; tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [tableView registerClass:[_STAlertViewCell class] forCellReuseIdentifier:@"Identifier"]; [self.contentView addSubview:tableView]; self.tableView = tableView; tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, footerHeight)]; tableView.tableFooterView.backgroundColor = [UIColor colorWithRed:0xFF/255. green:0x73/255. blue:0 alpha:1.0]; if (height > maxHeight) { tableView.scrollEnabled = YES; } else { tableView.scrollEnabled = NO; } __weak STAlertView *weakSelf = self; self.hitTestView = [[UIView alloc] init]; self.hitTestView.hitTestBlock = ^(CGPoint point, UIEvent *event, BOOL *returnSuper) { CGRect contentRect = [weakSelf.superview convertRect:weakSelf.frame toView:nil]; if (!CGPointInRect(point, contentRect)){ [weakSelf dismissActionFired:nil]; *returnSuper = YES; } return (UIView *)nil; }; self.hitTestView.backgroundColor = [UIColor clearColor]; } return self; } - (NSInteger)showInView:(UIView *)view animated:(BOOL)animated { self.hitTestView.frame = [UIScreen mainScreen].bounds; [[UIApplication sharedApplication].delegate.window addSubview:self.hitTestView]; // { self.tableView.contentInset = UIEdgeInsetsZero; if (!view) { view = [UIApplication sharedApplication].keyWindow; } [view addSubview:self]; self.frame = view.bounds; CGRect frame = self.contentView.frame; frame.size.width = CGRectGetWidth(view.bounds); self.backgroundView.alpha = 0.0; CGRect fromRect = frame, targetRect = frame; fromRect.size.height = 0; self.contentView.frame = fromRect; void (^animation)(void) = ^(void) { self.backgroundView.alpha = 0.5; self.contentView.frame = targetRect; }; void (^completion)(BOOL) = ^(BOOL finished) { }; if (animated) { [UIView animateWithDuration:0.35 animations:animation completion:completion]; } } while (!_shouldContinue) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } return _dismissedIndex; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataSource.count; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return _STAlertViewCellHeight; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { _STAlertViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:@"Identifier"]; tableViewCell.titleLabel.text = self.dataSource[indexPath.row]; return tableViewCell; } - (void)dismissAnimated:(BOOL)animated { [self _dismissAnimated:animated completion:^(BOOL finished){}]; } #pragma mark - PrivateMethod - (void)dismissActionFired:(UITapGestureRecognizer *)sender { _dismissedIndex = -1; [self _dismissAnimated:YES completion:^(BOOL finished){}]; } - (void)_dismissAnimated:(BOOL)animated completion:(void (^)(BOOL))_completion { self.backgroundView.alpha = 0.5; CGRect fromRect = self.contentView.frame, targetRect = self.contentView.frame; self.contentView.frame = fromRect; targetRect.size.height = 0; void (^animation)(void) = ^(void) { self.backgroundView.alpha = 0.0; self.contentView.frame = targetRect; }; void (^completion)(BOOL) = ^(BOOL finished) { _shouldContinue = YES; if (_completion) { _completion(finished); } [self removeFromSuperview]; [self.hitTestView removeFromSuperview]; }; if (animated) { [UIView animateWithDuration:0.35 animations:animation completion:completion]; } else { animation(); completion(YES); } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; _dismissedIndex = indexPath.row; [self dismissAnimated:YES]; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { CGPoint touchedPoint = [gestureRecognizer locationInView:self]; if (touchedPoint.y < CGRectGetMaxY(self.contentView.frame) && touchedPoint.y > CGRectGetMinX(self.contentView.frame)) { return NO; } return YES; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDCardTransitionDelegate.h ================================================ // // STDCardTransitionDelegate.h // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDTransitionDelegate.h" @interface STDCardTransitionDelegate : STDTransitionDelegate @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDCardTransitionDelegate.m ================================================ // // STDCardTransitionDelegate.m // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDCardTransitionDelegate.h" @implementation STDCardTransitionDelegate - (BOOL)navigationController:(STNavigationController *)navigationController shouldBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { return YES; } - (void)navigationController:(STNavigationController *)navigationController willBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { UIView *fromView = transitionContext.fromView, *toView = transitionContext.toView, *transitionView = transitionContext.transitionView; STViewControllerTransitionType transitionType = transitionContext.transitionType; fromView.layer.transform = toView.layer.transform = CATransform3DIdentity; fromView.left = 0; if (transitionType == STViewControllerTransitionTypePush) { toView.left = CGRectGetWidth(transitionView.bounds); } else { toView.left = - CGRectGetWidth(transitionView.bounds);; } } - (void)navigationController:(STNavigationController *)navigationController transitingWithContext:(STNavigationControllerTransitionContext *)transitionContext { UIView *fromView = transitionContext.fromView, *toView = transitionContext.toView, *transitionView = transitionContext.transitionView; CGFloat completion = transitionContext.completion; STViewControllerTransitionType transitionType = transitionContext.transitionType; [self _transformAppliedToFromView:fromView andToView:toView withTransitionView:transitionView completion:completion transitionType:transitionType]; } - (void)navigationController:(STNavigationController *)navigationController didEndTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { UIView *fromView = transitionContext.fromView, *toView = transitionContext.toView, *transitionView = transitionContext.transitionView; STViewControllerTransitionType transitionType = transitionContext.transitionType; fromView.layer.transform = toView.layer.transform = CATransform3DIdentity; toView.left = 0; if (transitionType == STViewControllerTransitionTypePush) { fromView.left = -CGRectGetWidth(transitionView.bounds); } else { fromView.left = CGRectGetWidth(transitionView.bounds); } } - (void)_transformAppliedToFromView:(UIView *)fromView andToView:(UIView *)toView withTransitionView:(UIView *)transitionView completion:(CGFloat)completion transitionType:(STViewControllerTransitionType)transitionType { UIView *leftView, *rightView; CGFloat width = CGRectGetWidth(transitionView.bounds); CGFloat leftAngel, leftHeight, leftX, rightAngel, rightHeight, rightX,currentPanOffset, leftPanOffset, rightPanOffset; BOOL leftXAxis, rightXAxis; CGFloat leftViewOffset = 0, rightViewOffset = width; if (transitionType == STViewControllerTransitionTypePush) { leftView = fromView, rightView = toView; currentPanOffset = width * completion; leftPanOffset = (currentPanOffset - leftViewOffset), rightPanOffset = (currentPanOffset - rightViewOffset); leftX = - completion * width; rightX = width - completion * width; } else { leftView = toView, rightView = fromView; currentPanOffset = width - width * completion; leftPanOffset = (currentPanOffset - leftViewOffset), rightPanOffset = (currentPanOffset - rightViewOffset); leftX = completion * width - width; rightX = completion * width; } leftAngel = leftPanOffset / width, rightAngel = rightPanOffset / width; CGFloat heightOffset = 80; leftHeight = heightOffset * (leftAngel < 0 ? -leftAngel : leftAngel), rightHeight = heightOffset * (rightAngel < 0 ? -rightAngel : rightAngel); leftXAxis = (currentPanOffset > leftViewOffset), rightXAxis = (currentPanOffset > rightViewOffset); leftView.layer.transform = CATransform3DIdentity; leftView.left = leftX; leftView.layer.transform = [self _transform3DWithAngle:leftAngel height:leftHeight xAxis:leftXAxis]; rightView.layer.transform = CATransform3DIdentity; rightView.left = rightX; rightView.layer.transform = [self _transform3DWithAngle:rightAngel height:rightHeight xAxis:rightXAxis]; } - (CATransform3D)_transform3DWithAngle:(CGFloat)angle height:(CGFloat)height xAxis:(BOOL)axis { CATransform3D transform = CATransform3DIdentity; transform.m34 = 1.0/-500; CGFloat x = axis ? 1 : -1; return CATransform3DRotate(transform, angle, x, 1, 0); } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDCoreDataManager.h ================================================ // // STDCoreDataManager.h // STKitDemo // // Created by SunJiangting on 15/8/11. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import @interface STDCoreDataManager : NSObject + (STCoreDataManager *)chatDataManager; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDCoreDataManager.m ================================================ // // STDCoreDataManager.m // STKitDemo // // Created by SunJiangting on 15/8/11. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDCoreDataManager.h" @implementation STDCoreDataManager static STCoreDataManager *_chatDataManager; + (STCoreDataManager *)chatDataManager { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSString *modelName = @"STDModel"; NSString *path = [STDocumentDirectory() stringByAppendingFormat:@"%@.sqlite", modelName]; _chatDataManager = [[STCoreDataManager alloc] initWithModelName:modelName dbFilePath:path]; }); return _chatDataManager; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDLoadingView.h ================================================ // // STDLoadingView.h // STKitDemo // // Created by SunJiangting on 15-4-2. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STDLoadingView : UIView @property(nonatomic) CGFloat completion; - (void)startAnimating; - (BOOL)isAnimating; - (void)stopAnimating; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDLoadingView.m ================================================ // // STDLoadingView.m // STKitDemo // // Created by SunJiangting on 15-4-2. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDLoadingView.h" #import @interface STDLoadingView () @property(nonatomic, strong) CAShapeLayer *shapeLayer; @property(nonatomic, strong) UIImageView *imageView; @end @implementation STDLoadingView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self _commonInitialize]; } return self; } - (void)awakeFromNib { [super awakeFromNib]; [self _commonInitialize]; } - (void)_commonInitialize { self.backgroundColor = [UIColor clearColor]; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = self.bounds; shapeLayer.fillColor = [UIColor st_colorWithRGB:0xFF7300].CGColor; [self.layer addSublayer:shapeLayer]; self.shapeLayer = shapeLayer; self.imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; NSMutableArray *images = [NSMutableArray arrayWithCapacity:8]; for (NSInteger i = 1; i <= 8; i ++) { NSString *imageName = [NSString stringWithFormat:@"%02ld", (long)i]; UIImage *image = [UIImage imageNamed:imageName]; if (image) { [images addObject:image]; } } self.imageView.image = [images firstObject]; self.imageView.animationImages = images; self.imageView.animationDuration = 0.5; self.imageView.hidden = YES; [self addSubview:self.imageView]; self.completion = 0; } - (void)setCompletion:(CGFloat)completion { _completion = completion; if (completion < 1 && !self.imageView.isAnimating) { [self _layoutWithCompletion:completion]; } else { [self _layoutWithCompletion:1]; self.imageView.frame = CGRectMake(self.inCenterX - 30, self.height - 60, 60, 60); self.imageView.hidden = NO; } } - (void)stopAnimating { self.imageView.hidden = YES; [self.imageView stopAnimating]; } - (void)startAnimating { if (!self.imageView.isAnimating) { [self.imageView startAnimating]; } } - (BOOL)isAnimating { return self.imageView.isAnimating; } - (void)_layoutWithCompletion:(CGFloat)completion { CGFloat width = 0, height = 0; self.imageView.hidden = YES; // 先从5到20----然后从20----40------>40 if (completion < 0.3) { CGFloat phaseCompletion = completion / 0.3; width = 3 + phaseCompletion * 12; height = width; } else if (completion < 0.7) { CGFloat phaseCompletion = (completion - 0.3) / 0.4; width = 15 + phaseCompletion * 5; height = 15 + phaseCompletion * 30; } else if (completion < 0.8) { CGFloat phaseCompletion = (completion - 0.7) / 0.1; width = 20 + phaseCompletion * 10; height = 45 - phaseCompletion * 15; } else { self.imageView.hidden = NO; CGFloat phaseCompletion = (completion - 0.8) / 0.2; width = 30 + phaseCompletion * 30; height = 30 + phaseCompletion * 30; } CGFloat x = (CGRectGetWidth(self.bounds) - width ) / 2; CGFloat y = CGRectGetHeight(self.bounds) - height; CGRect rect = CGRectMake(x, y, width, height); UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:rect]; self.shapeLayer.path = bezierPath.CGPath; self.imageView.frame = rect; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDRefreshControl.h ================================================ // // STDRefreshControl.h // STKitDemo // // Created by SunJiangting on 15-4-2. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STDRefreshControl : STRefreshControl @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDRefreshControl.m ================================================ // // TTRefreshControl.m // STKitDemo // // Created by SunJiangting on 15-4-2. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDRefreshControl.h" #import "STDLoadingView.h" @interface STDRefreshControl () @property(nonatomic, strong) STDLoadingView *loadingView; @end @implementation STDRefreshControl - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.loadingView = [[STDLoadingView alloc] initWithFrame:CGRectZero]; [self addSubview:self.loadingView]; self.minimumLoadingDuration = 2.0; } return self; } - (void)layoutSubviews { [super layoutSubviews]; self.loadingView.frame = self.bounds; } - (void)scrollViewDidChangeContentOffset:(CGPoint)contentOffset { CGFloat contentOffsetY = contentOffset.y; if (contentOffset.y < 0) { self.loadingView.completion = MIN(ABS(contentOffsetY) / self.threshold, 1); } } - (void)refreshControlDidChangedToState:(STRefreshControlState)refreshControlState { if (refreshControlState == STRefreshControlStateNormal) { [self.loadingView stopAnimating]; self.loadingView.completion = 0; } else if (refreshControlState == STRefreshControlStateLoading) { self.loadingView.completion = 1.0; [self.loadingView startAnimating]; } } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDRotateTransitionDelegate.h ================================================ // // STDRotateTransitionDelegate.h // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDTransitionDelegate.h" @interface STDRotateTransitionDelegate : STDTransitionDelegate @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDRotateTransitionDelegate.m ================================================ // // STDRotateTransitionDelegate.m // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDRotateTransitionDelegate.h" @implementation STDRotateTransitionDelegate - (BOOL)navigationController:(STNavigationController *)navigationController shouldBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { return YES; } - (void)navigationController:(STNavigationController *)navigationController willBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { UIView *targetView; CGFloat originAngle; if (transitionContext.transitionType == STViewControllerTransitionTypePop) { targetView = transitionContext.fromView; originAngle = 0; } else { targetView = transitionContext.toView; originAngle = M_PI_2; } targetView.anchorPoint = CGPointMake(0.0, 1.0); targetView.layer.transform = CATransform3DMakeRotation(originAngle, 0.0, .0, 1.0); } - (void)navigationController:(STNavigationController *)navigationController transitingWithContext:(STNavigationControllerTransitionContext *)transitionContext { CGFloat completion = transitionContext.completion; UIView *fromView = transitionContext.fromView, *toView = transitionContext.toView; STViewControllerTransitionType transitionType = transitionContext.transitionType; UIView *targetView; if (transitionType == STViewControllerTransitionTypePop) { targetView = fromView; } else { targetView = toView; completion = (1.0 - completion); } targetView.layer.transform = CATransform3DMakeRotation(M_PI_2 * completion, 0.0, .0, 1.0); } - (void)navigationController:(STNavigationController *)navigationController didEndTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { UIView *fromView = transitionContext.fromView, *toView = transitionContext.toView; fromView.anchorPoint = CGPointMake(0.5, 0.5); fromView.layer.transform = CATransform3DIdentity; toView.anchorPoint = CGPointMake(0.5, 0.5); toView.layer.transform = CATransform3DIdentity; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDScrollViewController.h ================================================ // // STDScrollViewController.h // STKitDemo // // Created by SunJiangting on 15-4-7. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDScrollView : UIView @property(nonatomic, strong) UIView *headerView; @end @interface STDScrollViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDScrollViewController.m ================================================ // // STDScrollViewController.m // STKitDemo // // Created by SunJiangting on 15-4-7. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDScrollViewController.h" #import "STDRefreshControl.h" #import @interface UIView (STDWebViewHeader) @property(nonatomic) CGFloat headerOffset; @end @implementation UIView (STDWebViewHeader) static NSString *const STDViewHeaderOffsetKey = @"STDViewHeaderOffsetKey"; - (void)setHeaderOffset:(CGFloat)headerOffset { objc_setAssociatedObject(self, (__bridge const void *)(STDViewHeaderOffsetKey), @(headerOffset), OBJC_ASSOCIATION_COPY_NONATOMIC); } - (CGFloat)headerOffset { NSNumber *value = objc_getAssociatedObject(self, (__bridge const void *)(STDViewHeaderOffsetKey)); return [value floatValue]; } @end @interface STDWebView : UIWebView @property(nonatomic, strong) UIView *webHeaderView; @end @implementation STDWebView - (void)setWebHeaderView:(UIView *)webHeaderView { if (_webHeaderView) { [_webHeaderView removeFromSuperview]; } _webHeaderView = webHeaderView; [self.scrollView addSubview:webHeaderView]; [self.scrollView.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { if (subview != webHeaderView) { subview.top += (webHeaderView.height - subview.headerOffset); subview.headerOffset = webHeaderView.height; } }]; } - (void)layoutSubviews { [super layoutSubviews]; } @end @interface STDScrollViewController () @property(nonatomic, strong) UIView *headerView; @property(nonatomic, strong) STDWebView *webView; @property(nonatomic, strong) STScrollDirector *scrollDirector; @end @implementation STDScrollViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.hidesBottomBarWhenPushed = YES; self.edgesForExtendedLayout = UIRectEdgeNone; self.scrollDirector = [[STScrollDirector alloc] init]; STDRefreshControl *refreshControl = [[STDRefreshControl alloc] initWithFrame:CGRectMake(0, 0, 200, 76)]; refreshControl.threshold = 76; self.scrollDirector.refreshControl = refreshControl; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"WebViewHeaderView"; self.headerView = [[UIView alloc] initWithFrame:self.view.bounds]; self.headerView.height = 200; self.headerView.backgroundColor = [UIColor redColor]; self.webView = [[STDWebView alloc] initWithFrame:self.view.bounds]; // CGRectMake(0, self.headerView.bottom, self.view.width, self.view.height - self.headerView.bottom)]; self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.webView.webHeaderView = self.headerView; // [self.webView.scrollView.panGestureRecognizer addTarget:self action:@selector(_webScrollViewPanActionFired:)]; // self.webView.delegate = self; [self.webView.scrollView addSubview:self.headerView]; self.webView.scrollView.delegate = self; [self.view addSubview:self.webView]; // [self.view addSubview:self.headerView]; // self.scrollDirector.scrollView = self.webView.scrollView; // [self.scrollDirector.refreshControl addTarget:self.webView action:@selector(reload) forControlEvents:UIControlEventValueChanged]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://suenblog.duapp.com"]]]; } - (void)_webScrollViewPanActionFired:(UIPanGestureRecognizer *)panGestureRecognizer { if (panGestureRecognizer.state != UIGestureRecognizerStateChanged) { return; } UIScrollView *scrollView = self.webView.scrollView; CGPoint contentOffset = scrollView.contentOffset; CGFloat offsetY = contentOffset.y; if (offsetY <= 0) { self.webView.top = - offsetY + self.headerView.height; self.headerView.top = - offsetY; } else if (offsetY >= self.headerView.height) { self.webView.top = 0; self.webView.height = self.view.height; self.headerView.top = - offsetY; contentOffset.y = offsetY - self.headerView.height; } else { self.webView.top = self.headerView.height - offsetY; self.headerView.top = - offsetY; self.webView.height = self.view.height - self.headerView.bottom; contentOffset.y = 0; } scrollView.contentOffset = contentOffset; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { return; CGPoint contentOffset = scrollView.contentOffset; CGFloat offsetY = contentOffset.y; if (offsetY <= 0) { self.webView.top = - offsetY + self.headerView.height; self.headerView.top = - 2 * offsetY; // contentOffset.y = 0; } else if (offsetY >= self.headerView.height) { self.webView.top = 0; self.webView.height = self.view.height; self.headerView.top = - offsetY; } else { self.webView.top = self.headerView.height - offsetY; self.headerView.top = - 2 * offsetY; self.webView.height = self.view.height - self.headerView.bottom; } } - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView { return YES; } - (void)webViewDidFinishLoad:(UIWebView *)webView { [self.scrollDirector.refreshControl endRefreshing]; } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { [self.scrollDirector.refreshControl endRefreshing]; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTabBarController.h ================================================ // // STDTabBarController.h // STKitDemo // // Created by SunJiangting on 14-2-18. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STDTabBarController : STTabBarController @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTabBarController.m ================================================ // // STDTabBarController.m // STKitDemo // // Created by SunJiangting on 14-2-18. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTabBarController.h" #import "STARootViewController.h" #import "STDMoreViewController.h" #import "STDemoViewController.h" #import "STDServiceViewController.h" #import "STDSettingViewController.h" #import "STDCardTransitionDelegate.h" #import "STDRotateTransitionDelegate.h" @interface STDTabBarController () @end @implementation STDTabBarController - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { STDemoViewController *controlsViewController = [[STDemoViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *controlsNavigationController = [[STNavigationController alloc] initWithRootViewController:controlsViewController]; controlsNavigationController.st_tabBarItem = [[STTabBarItem alloc] initWithTitle:@"组件" image:[UIImage imageNamed:@"tab_receipt_normal.png"] selectedImage:[UIImage imageNamed:@"tab_receipt_highlighted.png"]]; STDServiceViewController *serviceViewController = [[STDServiceViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *serviceNavigationController = [[STNavigationController alloc] initWithRootViewController:serviceViewController]; serviceNavigationController.st_tabBarItem = [[STTabBarItem alloc] initWithTitle:@"服务" image:[UIImage imageNamed:@"tab_service_normal.png"] selectedImage:[UIImage imageNamed:@"tab_service_highlighted.png"]]; STDMoreViewController *moreViewController = [[STDMoreViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *moreNavigationController = [[STNavigationController alloc] initWithRootViewController:moreViewController]; moreNavigationController.st_tabBarItem = [[STTabBarItem alloc] initWithTitle:@"我的" image:[UIImage imageNamed:@"tab_profile_normal.png"] selectedImage:[UIImage imageNamed:@"tab_profile_highlighted.png"]]; self.viewControllers = @[controlsNavigationController, serviceNavigationController, moreNavigationController]; self.st_sideInteractionArea = STSideInteractiveAreaNone; self.animatedWhenTransition = ![STDSettingViewController reduceTransitionAnimation]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. if (STGetSystemVersion() < 7) { self.actualTabBarHeight = 42; self.tabBar.backgroundImage = [[UIImage imageNamed:@"tab_bkg.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(30, 2, 10, 2) resizingMode:UIImageResizingModeStretch]; } if (![[[STPersistence standardPersistence] valueForKey:@"STHasEnteredAboutViewController"] boolValue]) { [self setBadgeValue:@"New" forIndex:2]; } [self reloadNavigationTransitionDelegate]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadNavigationTransitionDelegate) name:@"STDAllowsCustomNavigationTransitionDidChangeNotification" object:nil]; } - (void)reloadNavigationTransitionDelegate { STNavigationController *navigationController = (STNavigationController *)[self.viewControllers firstObject]; if ([navigationController isKindOfClass:[STNavigationController class]]) { navigationController.delegate = [STDSettingViewController allowsCustomNavigationTransition]?[STDRotateTransitionDelegate sharedDelegate]:nil; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTableViewController.h ================================================ // // STDTableViewController.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STDViewController.h" @interface STDTableViewController : STModelViewController - (instancetype)initWithStyle:(UITableViewStyle) tableViewStyle; @property(nonatomic, readonly, strong) UITableView *tableView; @property(nonatomic, assign) BOOL clearsSelectionOnViewWillAppear; @property(nonatomic, strong, readonly) STScrollDirector *scrollDirector; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTableViewController.m ================================================ // // STDTableViewController.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDTableViewController.h" @interface STDTableViewController () @property(nonatomic, strong) UITableView *tableView; @property(nonatomic, assign) UITableViewStyle tableViewStyle; @property(nonatomic, strong) STScrollDirector *scrollDirector; @end @implementation STDTableViewController - (instancetype) initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithNibName:nil bundle:nil]; if (self) { self.tableViewStyle = tableViewStyle; self.clearsSelectionOnViewWillAppear = YES; self.scrollDirector = [[STScrollDirector alloc] init]; [self.scrollDirector setTitle:@"下拉可以刷新" forState:STScrollDirectorStateRefreshNormal]; [self.scrollDirector setTitle:@"松手开始刷新" forState:STScrollDirectorStateRefreshReachedThreshold]; [self.scrollDirector setTitle:@"正在刷新..." forState:STScrollDirectorStateRefreshLoading]; [self.scrollDirector setTitle:@"加载更多" forState:STScrollDirectorStatePaginationNormal]; [self.scrollDirector setTitle:@"正在加载更多" forState:STScrollDirectorStatePaginationLoading]; [self.scrollDirector setTitle:@"重新加载" forState:STScrollDirectorStatePaginationFailed]; [self.scrollDirector setTitle:@"没有更多了" forState:STScrollDirectorStatePaginationReachedEnd]; } return self; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { return [self initWithStyle:UITableViewStylePlain]; } - (void)loadView { [super loadView]; self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:self.tableViewStyle]; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.tableView.dataSource = self; self.tableView.delegate = self; self.tableView.backgroundView = nil; self.tableView.backgroundColor = [UIColor clearColor]; [self.view addSubview:self.tableView]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. CGFloat value = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultEdgeOffset"] doubleValue]; if (value == 0) { value = 80; [[STPersistence standardPersistence] setValue:@(value) forKey:@"STDNavigationDefaultEdgeOffset"]; } self.st_maximumInteractivePopEdgeDistance = value; CGFloat value1 = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultOffset"] floatValue]; if (value1 == 0) { value1 = 80; [[STPersistence standardPersistence] setValue:@(value1) forKey:@"STDNavigationDefaultOffset"]; } self.st_interactivePopTransitionOffset = value1; // Do any additional setup after loading the view, typically from a nib. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(maximumInteractiveDistanceChanged:) name:@"STDNavigationDefaultEdgeOffset" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(maximumInteractiveOffsetChanged:) name:@"STDNavigationDefaultOffset" object:nil]; self.scrollDirector.scrollView = self.tableView; [self.scrollDirector.refreshControl addTarget:self action:@selector(_refreshControlActionFired:) forControlEvents:UIControlEventValueChanged]; [self.scrollDirector.paginationControl addTarget:self action:@selector(_paginationControlActionFired:) forControlEvents:UIControlEventValueChanged]; } - (void)maximumInteractiveDistanceChanged:(id)sender { self.st_maximumInteractivePopEdgeDistance = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultEdgeOffset"] floatValue]; } - (void)maximumInteractiveOffsetChanged:(id)sender { self.st_interactivePopTransitionOffset = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultOffset"] floatValue]; } - (void)_refreshControlActionFired:(STRefreshControl *)refreshControl { [self.model loadDataFromRemote]; } - (void)_paginationControlActionFired:(id) sender { [self.model loadDataFromPagination]; } - (void)modelDidFinishLoadData:(STModel *)model { [super modelDidFinishLoadData:model]; if (model.sourceType == STModelDataSourceTypeRemote) { [self.scrollDirector.refreshControl endRefreshing]; } [self _reloadTableFooterView]; [self.tableView reloadData]; } - (void)modelDidFailedLoadData:(STModel *)model { [super modelDidFailedLoadData:model]; if (model.sourceType == STModelDataSourceTypeRemote) { [self.scrollDirector.refreshControl endRefreshing]; } else { if (model.sourceType == STModelDataSourceTypePagination) { self.scrollDirector.paginationControl.paginationState = STPaginationControlStateFailed; self.tableView.tableFooterView = self.scrollDirector.paginationControl; } } [self.tableView reloadData]; } - (void)_reloadTableFooterView { if (self.model.hasNextPage) { self.scrollDirector.paginationControl.paginationState = STPaginationControlStateNormal; } else { self.scrollDirector.paginationControl.paginationState = STPaginationControlStateReachedEnd; } self.tableView.tableFooterView = self.scrollDirector.paginationControl; } - (void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (self.clearsSelectionOnViewWillAppear) { [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { /// config Cell return nil; } - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return nil; } - (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTextTableViewController.h ================================================ // // STDTextTableViewController.h // STKitDemo // // Created by SunJiangting on 14-10-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTableViewController.h" @interface STDTableViewCellItem : STObject - (instancetype)initWithTitle:(NSString *)title target:(id)target action:(SEL)action; @property(nonatomic, copy) NSString *title; //// Cell 点击时的响应事件 @property(nonatomic, weak) id target; /// action Must have zero argument like someRowClicked {} @property(nonatomic, assign) SEL action; @property(nonatomic, strong) id contextInfo; @property(nonatomic) BOOL switchStyle; @property(nonatomic) BOOL checked; @end @interface STDTableViewSectionItem : STObject - (instancetype)initWithSectionTitle:(NSString *)title items:(NSArray *)items; @property(nonatomic, copy) NSString *title; @property(nonatomic, copy) NSArray *items; @end /// 内容都为文本,不做任何定制化的tableView @interface STDTextTableViewController : STDTableViewController /// 默认的dataSource, @see STDTableViewSectionItem @property(nonatomic, copy) NSArray *dataSource; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTextTableViewController.m ================================================ // // STDTextTableViewController.m // STKitDemo // // Created by SunJiangting on 14-10-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTextTableViewController.h" @interface STDTextStyleCell : UITableViewCell @property(nonatomic, strong) UISwitch *switchView; @property(nonatomic, strong) STDTableViewCellItem *cellItem; @end @implementation STDTextStyleCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.switchView = [[UISwitch alloc] init]; self.accessoryView = self.switchView; [self.switchView addTarget:self action:@selector(_switchActionFired:) forControlEvents:UIControlEventTouchUpInside]; self.textLabel.highlightedTextColor = [UIColor lightGrayColor]; } return self; } - (void)setCellItem:(STDTableViewCellItem *)cellItem { self.accessoryView = cellItem.switchStyle ? self.switchView : nil; self.selectionStyle = cellItem.switchStyle ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault; self.switchView.on = cellItem.checked; _cellItem = cellItem; } - (void)_switchActionFired:(UISwitch *)uiswitch { [self.cellItem.target st_performSelector:_cellItem.action withObjects:uiswitch, nil]; self.cellItem.checked = uiswitch.on; } @end @implementation STDTableViewCellItem - (instancetype)initWithTitle:(NSString *)title target:(id)target action:(SEL)action { self = [super init]; if (self) { self.title = title; self.target = target; self.action = action; } return self; } @end @implementation STDTableViewSectionItem - (instancetype)initWithSectionTitle:(NSString *)title items:(NSArray *)items { self = [super init]; if (self) { self.title = title; self.items = items; } return self; } @end @interface STDTextTableViewController () @end @implementation STDTextTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.scrollDirector.refreshControl.enabled = NO; self.tableView.backgroundColor = [UIColor st_colorWithRGB:0xF5F5F5]; [self.tableView registerClass:[STDTextStyleCell class] forCellReuseIdentifier:@"Identifier"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { STDTableViewSectionItem *sectionItem = [self.dataSource objectAtIndex:section]; if ([sectionItem isKindOfClass:[STDTableViewSectionItem class]]) { return sectionItem.title; } return nil; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return self.dataSource.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. STDTableViewSectionItem *sectionItem = [self.dataSource objectAtIndex:section]; if ([sectionItem isKindOfClass:[STDTableViewSectionItem class]]) { return sectionItem.items.count; } return 0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { STDTextStyleCell *tableViewCell = (STDTextStyleCell *)[tableView dequeueReusableCellWithIdentifier:@"Identifier"]; STDTableViewSectionItem *sectionItem = [self.dataSource objectAtIndex:indexPath.section]; STDTableViewCellItem *item = sectionItem.items[indexPath.row]; if ([item isKindOfClass:[STDTableViewCellItem class]]) { tableViewCell.textLabel.text = item.title; if ([tableViewCell isKindOfClass:[STDTextStyleCell class]]) { tableViewCell.cellItem = item; } } else { tableViewCell.textLabel.text = @"配置出现问题"; } return tableViewCell; } - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { if (![view isKindOfClass:[UITableViewHeaderFooterView class]]) { return; } UILabel *textLabel = ((UITableViewHeaderFooterView *)view).textLabel; STDTableViewSectionItem *sectionItem = [self.dataSource objectAtIndex:section]; if ([sectionItem isKindOfClass:[STDTableViewSectionItem class]]) { textLabel.text = sectionItem.title; } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; STDTableViewSectionItem *sectionItem = [self.dataSource objectAtIndex:indexPath.section]; STDTableViewCellItem *item = sectionItem.items[indexPath.row]; if ([item isKindOfClass:[STDTableViewCellItem class]] && [item.target respondsToSelector:item.action]) { [item.target st_performSelector:item.action withObjects:nil, nil]; } } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTransitionDelegate.h ================================================ // // STDTransitionDelegate.h // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STDTransitionDelegate : NSObject + (instancetype)sharedDelegate; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDTransitionDelegate.m ================================================ // // STDTransitionDelegate.m // STKitDemo // // Created by SunJiangting on 15-4-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDTransitionDelegate.h" @implementation STDTransitionDelegate static id _sharedDelegate; + (instancetype)sharedDelegate { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedDelegate = [[self alloc] init]; }); return _sharedDelegate; } - (BOOL)navigationController:(STNavigationController *)navigationController shouldBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { return NO; } - (void)navigationController:(STNavigationController *)navigationController willBeginTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { } - (void)navigationController:(STNavigationController *)navigationController transitingWithContext:(STNavigationControllerTransitionContext *)transitionContext { } - (void)navigationController:(STNavigationController *)navigationController didEndTransitionContext:(STNavigationControllerTransitionContext *)transitionContext { } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDViewController.h ================================================ // // STDViewController.h // STKitDemo // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @interface STDViewController : STViewController @property (nonatomic, assign) BOOL customizeEdgeOffset; @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDViewController.m ================================================ // // STDViewController.m // STKitDemo // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDViewController () @property(nonatomic, strong) UIView *presentationView; @end @implementation STDViewController - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.customizeEdgeOffset = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor st_colorWithRGB:0xF9F9F9]; self.presentationView = [[UIView alloc] initWithFrame:self.view.bounds]; self.presentationView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; // [self.view addSubview:self.presentationView]; UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerActionFired:)]; [self.presentationView addGestureRecognizer:panGestureRecognizer]; __weak STDViewController *weakSelf = self; self.presentationView.hitTestBlock = ^(CGPoint point, UIEvent *event, BOOL *returnSuper) { if (ABS(CGRectGetWidth(weakSelf.view.frame) - point.x) < 20) { *returnSuper = YES; return (UIView *)nil; } return (UIView *)nil; }; if (STGetSystemVersion() < 7) { self.st_navigationBar.backgroundImage = [UIImage imageNamed:@"header_bkg"]; } CGFloat value = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultEdgeOffset"] floatValue]; if (value == 0) { value = 80; [[STPersistence standardPersistence] setValue:@(value) forKey:@"STDNavigationDefaultEdgeOffset"]; } if (self.customizeEdgeOffset) { self.st_maximumInteractivePopEdgeDistance = value; } CGFloat value1 = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultOffset"] floatValue]; if (value1 == 0) { value1 = 80; [[STPersistence standardPersistence] setValue:@(value1) forKey:@"STDNavigationDefaultOffset"]; } self.st_interactivePopTransitionOffset = value1; // Do any additional setup after loading the view, typically from a nib. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(maximumInteractiveDistanceChanged:) name:@"STDNavigationDefaultEdgeOffset" object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(maximumInteractiveOffsetChanged:) name:@"STDNavigationDefaultOffset" object:nil]; } - (void)maximumInteractiveDistanceChanged:(id)sender { self.st_maximumInteractivePopEdgeDistance = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultEdgeOffset"] floatValue]; } - (void)maximumInteractiveOffsetChanged:(id)sender { if (self.customizeEdgeOffset) { self.st_interactivePopTransitionOffset = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultOffset"] floatValue]; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)panGestureRecognizerActionFired:(UIPanGestureRecognizer *)sender { switch (sender.state) { case UIGestureRecognizerStateBegan: [self panGestureDidBegan:sender]; break; case UIGestureRecognizerStateChanged: [self panGestureDidChanged:sender]; break; case UIGestureRecognizerStateCancelled: case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateFailed: [self panGestureDidCancelled:sender]; break; default: break; } } static UIView *_statusBarSuperview; - (void)panGestureDidBegan:(UIPanGestureRecognizer *)sender { // _statusBarSuperview = self.view.statusBarWindow.superview; // [self.view.statusBarWindow removeFromSuperview]; // [self.view addSubview:self.view.statusBarWindow]; // self.view.layer.masksToBounds = NO; // self.view.clipsToBounds = NO; } - (void)panGestureDidChanged:(UIPanGestureRecognizer *)sender { CGPoint translation = [sender translationInView:self.view]; if (ABS(translation.x) < 160) { CGFloat maximumAngel = M_PI_2; CATransform3D transform = CATransform3DMakeRotation(maximumAngel * (ABS(translation.x) / 240.0), 0., 1.0, 0.0); self.view.layer.transform = transform; CGFloat percent = ABS(translation.x) / 160.0f; [self transformView:self.view offset:-5 percent:percent]; } } - (void)transformView:(UIView *)view offset:(CGFloat)offset percent:(CGFloat)percent { [view.subviews enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) { [self transformView:obj offset:(offset - 5)percent:percent]; CATransform3D transform1 = CATransform3DMakeTranslation(offset * 0.2 * percent, -offset * percent, 0); // transform = CATransform3DRotate(transform, 85 * M_PI / 180, .0, 1.0, 0); CATransform3D transform2 = CATransform3DMakeRotation(M_PI * 0.2 * percent, 0.5, 1.0, .0); CATransform3D transform = CATransform3DConcat(transform1, transform2); transform.m34 = -1.0 / 250.0; obj.layer.transform = transform; }]; } - (void)resetView:(UIView *)view { [view.subviews enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) { [self resetView:obj]; obj.layer.transform = CATransform3DIdentity; }]; } - (void)panGestureDidCancelled:(UIPanGestureRecognizer *)sender { [self resetView:self.view]; self.view.layer.transform = CATransform3DIdentity; // [self.view.statusBarWindow removeFromSuperview]; // [_statusBarSuperview addSubview:self.view.statusBarWindow]; } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDropMenuView.h ================================================ // // STDropMenuView.h // STKitDemo // // Created by SunJiangting on 14-8-14. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STDropMenuView : STPopoverView - (instancetype) initWithMenuTitles:(NSString *) menuTitle, ... NS_REQUIRES_NIL_TERMINATION; @property (nonatomic, strong) void (^ dismissHandler) (STDropMenuView * dropView, NSInteger index); @end ================================================ FILE: STKitDemo/Classes/BaseUI/STDropMenuView.m ================================================ // // STDropMenuView.m // STKitDemo // // Created by SunJiangting on 14-8-14. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDropMenuView.h" @interface _STDropMenuCell : UITableViewCell @property(nonatomic, strong) UILabel *titleLabel; @property(nonatomic, strong) UIView *separatorView; @end const CGFloat _STDropMenuCellHeight = 45; @implementation _STDropMenuCell - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.frame = CGRectMake(0, 0, 320, _STDropMenuCellHeight); self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 300, 44)]; self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.titleLabel.textColor = [UIColor darkGrayColor]; self.titleLabel.highlightedTextColor = [UIColor whiteColor]; self.titleLabel.font = [UIFont systemFontOfSize:17.]; self.titleLabel.textAlignment = NSTextAlignmentCenter; [self addSubview:self.titleLabel]; self.separatorView = [[UIView alloc] initWithFrame:CGRectZero]; [self addSubview:self.separatorView]; } return self; } - (void)setFrame:(CGRect)frame { [super setFrame:frame]; self.separatorView.frame = CGRectMake(0, CGRectGetHeight(frame) - STOnePixel(), CGRectGetWidth(frame), STOnePixel()); } - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated { [super setHighlighted:highlighted animated:animated]; self.separatorView.backgroundColor = [UIColor st_colorWithRGB:0x999999]; } @end @interface STDropMenuView () @property(nonatomic, strong) NSMutableArray *dataSource; @property(nonatomic, strong) UITableView *tableView; @end @implementation STDropMenuView - (instancetype)initWithMenuTitles:(NSString *)menuTitle, ... NS_REQUIRES_NIL_TERMINATION { NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:1]; NSString *title = nil; va_list args; if (menuTitle) { [dataSource addObject:menuTitle]; va_start(args, menuTitle); while ((title = va_arg(args, NSString *))) { [dataSource addObject:title]; } va_end(args); } self = [super initWithFrame:CGRectZero]; if (self) { self.dataSource = dataSource; self.contentOffset = CGPointMake(0, 64); self.direction = STPopoverViewDirectionDown; CGFloat maxHeight = 240; const CGFloat footerHeight = 1; CGFloat height = dataSource.count * _STDropMenuCellHeight + footerHeight; STTableView *tableView = [[STTableView alloc] initWithFrame:CGRectMake(0, STOnePixel(), CGRectGetWidth([UIScreen mainScreen].applicationFrame), MIN(height, maxHeight)) style:UITableViewStylePlain]; tableView.scrollsToTop = NO; tableView.delegate = self; tableView.dataSource = self; tableView.backgroundView = nil; tableView.separatorStyle = UITableViewCellSeparatorStyleNone; tableView.userInteractionEnabled = YES; [tableView registerClass:[_STDropMenuCell class] forCellReuseIdentifier:@"Identifier"]; [self.contentView addSubview:tableView]; self.tableView = tableView; tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, footerHeight)]; tableView.tableFooterView.backgroundColor = [UIColor st_colorWithRGB:0xFF7300]; if (height > maxHeight) { tableView.scrollEnabled = YES; } else { tableView.scrollEnabled = NO; } } return self; } - (void)showInView:(UIView *)view animated:(BOOL)animated { [super showInView:view animated:YES]; self.tableView.contentInset = UIEdgeInsetsZero; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataSource.count; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return _STDropMenuCellHeight; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { _STDropMenuCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:@"Identifier"]; tableViewCell.titleLabel.text = self.dataSource[indexPath.row]; return tableViewCell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; [self dismissAnimated:YES]; if (self.dismissHandler) { self.dismissHandler(self, indexPath.row); } } @end ================================================ FILE: STKitDemo/Classes/BaseUI/STMenuView.h ================================================ // // STMenuView.h // STKitDemo // // Created by SunJiangting on 14-3-24. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STMenuItem : NSObject @property(nonatomic, strong) UIImage *image; @property(nonatomic, strong) UIImage *highlightedImage; @property(nonatomic, strong) NSString *title; - (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage title:(NSString *)title; @end @class STMenuView; typedef void (^STMenuDismissHandler)(STMenuView *menuView, int dismissIndex); @interface STMenuView : UIView @property(nonatomic, strong) STMenuDismissHandler dismissHandler; /// default initializer - (instancetype)initWithDelegate:(id)delegate menuItem:(STMenuItem *)menuItem, ... NS_REQUIRES_NIL_TERMINATION; - (instancetype)initWithDelegate:(id)delegate menuItems:(NSArray *)menuItems; /// if view==nil, view = keyWindow - (void)showInView:(UIView *)view animated:(BOOL)animated; - (void)dismissAnimated:(BOOL)animated; - (STMenuItem *)menuItemAtIndex:(NSUInteger)index; @end extern const CGSize STMenuItemImageSize; ================================================ FILE: STKitDemo/Classes/BaseUI/STMenuView.m ================================================ // // STMenuView.m // STKitDemo // // Created by SunJiangting on 14-3-24. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STMenuView.h" #import #import @implementation STMenuItem : NSObject - (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage title:(NSString *)title { self = [super init]; if (self) { self.title = title; self.image = image; self.highlightedImage = highlightedImage; } return self; } @end @interface STMenuView () @property(nonatomic, strong) UIImageView *blurView; @property(nonatomic, strong) NSMutableArray *dataSource; @property(nonatomic, strong) UIButton *dismissButton; @property(nonatomic, strong) NSMutableArray *menuItemViews; @end @implementation STMenuView - (void)dealloc { // [self.hitTestButton removeObserver:self forKeyPath:@"highlighted"]; } - (instancetype)initWithDelegate:(id)delegate menuItem:(STMenuItem *)menuItem0, ... { NSMutableArray *menuItems = [NSMutableArray arrayWithCapacity:1]; STMenuItem *menuItem = nil; va_list args; if (menuItem0) { [menuItems addObject:menuItem0]; va_start(args, menuItem0); while ((menuItem = va_arg(args, STMenuItem *))) { [menuItems addObject:menuItem]; } va_end(args); } return [self initWithDelegate:delegate menuItems:menuItems]; } - (instancetype)initWithDelegate:(id)delegate menuItems:(NSArray *)menuItems { self = [super initWithFrame:CGRectZero]; if (self) { self.dataSource = [NSMutableArray arrayWithArray:menuItems]; self.menuItemViews = [NSMutableArray arrayWithCapacity:menuItems.count]; self.blurView = [[UIImageView alloc] initWithFrame:self.bounds]; self.blurView.userInteractionEnabled = YES; self.blurView.backgroundColor = [UIColor clearColor]; self.blurView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.blurView.contentMode = UIViewContentModeScaleAspectFit; [self addSubview:self.blurView]; UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureActionFired:)]; panGestureRecognizer.delegate = self; [self.blurView addGestureRecognizer:panGestureRecognizer]; UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureActionFired:)]; tapGestureRecognizer.delegate = self; [self.blurView addGestureRecognizer:tapGestureRecognizer]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setTitle:@"取消" forState:UIControlStateNormal]; [button setBackgroundImage:[UIImage imageNamed:@"aero_button"] forState:UIControlStateHighlighted]; [button addTarget:self action:@selector(dismissAnimated:) forControlEvents:UIControlEventTouchUpInside]; [self.blurView addSubview:button]; [self reloadMenuItems]; self.dismissButton = button; UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(20, 20, 280, 40)]; slider.minimumValue = 50; slider.maximumValue = 100; slider.value = 100; [slider addTarget:self action:@selector(sliderValueActionFired:) forControlEvents:UIControlEventValueChanged]; [self.blurView addSubview:slider]; } return self; } - (void)sliderValueActionFired:(UISlider *)slider { self.blurView.alpha = slider.value / 100; } - (STMenuItem *)menuItemAtIndex:(NSUInteger)index { return [self.dataSource objectAtIndex:index]; } - (void)reloadMenuItems { [self.menuItemViews enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { [view removeFromSuperview]; }]; [self.menuItemViews removeAllObjects]; [self.dataSource enumerateObjectsUsingBlock:^(STMenuItem *menuItem, NSUInteger idx, BOOL *stop) { STButton *button = [STButton buttonWithType:UIButtonTypeCustom]; button.usingSystemLayout = NO; button.imageView.image = menuItem.image; button.titleLabel.text = menuItem.title; [self.blurView addSubview:button]; [self.menuItemViews addObject:button]; }]; } - (void)showInView:(UIView *)view animated:(BOOL)animated { if (!view) { view = [UIApplication sharedApplication].keyWindow; } UIImage *snapView = [view st_snapshotImage]; UIImage *image = [snapView st_blurImageWithStyle:STBlurEffectStyleLight]; self.blurView.image = image; self.frame = view.bounds; [view addSubview:self]; self.dismissButton.frame = CGRectMake(0, CGRectGetHeight(view.frame) - 49, CGRectGetWidth(view.frame), 49); [self layoutMenuItems]; self.blurView.alpha = 0; void (^animation)(void) = ^{ self.blurView.alpha = 1.0; }; void (^completion)(BOOL) = ^(BOOL finished) { self.blurView.alpha = 1.0; }; [self riseAnimation]; if (animated) { [UIView animateWithDuration:0.35 animations:animation completion:completion]; } else { animation(); completion(YES); } } - (CGRect)frameForMenuAtIndex:(NSUInteger)index { NSUInteger columnCount = 3; NSUInteger columnIndex = index % columnCount; NSUInteger rowCount = self.menuItemViews.count / columnCount + (self.menuItemViews.count % columnCount > 0 ? 1 : 0); NSUInteger rowIndex = index / columnCount; CGFloat itemHeight = (STMenuItemImageSize.height + 20) * rowCount + (rowCount > 1 ? (rowCount - 1) * 10 : 0); CGFloat offsetY = (CGRectGetHeight(self.bounds) - itemHeight - CGRectGetHeight(self.dismissButton.bounds)) / 2.0; CGFloat verticalPadding = (CGRectGetWidth(self.bounds) - 10 * 2 - STMenuItemImageSize.height * 3) / 2.0; CGFloat offsetX = 10; offsetX += (STMenuItemImageSize.height + verticalPadding) * columnIndex; offsetY += (STMenuItemImageSize.height + 30) * rowIndex; return CGRectMake(offsetX, offsetY, STMenuItemImageSize.width, STMenuItemImageSize.width + 20); } - (void)layoutMenuItems { [self.menuItemViews enumerateObjectsUsingBlock:^(STButton *subview, NSUInteger idx, BOOL *stop) { subview.frame = [self frameForMenuAtIndex:idx]; subview.imageView.frame = CGRectMake(0, 0, STMenuItemImageSize.width, STMenuItemImageSize.height); subview.titleLabel.frame = CGRectMake(0, STMenuItemImageSize.height, STMenuItemImageSize.width, 20); }]; } - (void)dismissAnimated:(BOOL)animated { [self dropAnimation]; self.blurView.alpha = 1.0; void (^animation)(void) = ^{ self.blurView.alpha = 0.0; }; void (^completion)(BOOL) = ^(BOOL finished) { self.blurView.alpha = 0.0; self.blurView.image = nil; [self.menuItemViews enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) { [obj.layer removeAllAnimations]; }]; [self removeFromSuperview]; }; if (animated) { [UIView animateWithDuration:0.35 animations:animation completion:completion]; } else { animation(); completion(YES); } [[NSURLCache sharedURLCache] setMemoryCapacity:1024]; } - (void)hitButtonTouchUpInside:(UIButton *)sender { [self.dismissButton sendActionsForControlEvents:UIControlEventTouchUpInside]; } - (void)riseAnimation { NSUInteger columnCount = 3; NSUInteger rowCount = self.menuItemViews.count / columnCount + (self.menuItemViews.count % columnCount > 0 ? 1 : 0); [self.menuItemViews enumerateObjectsUsingBlock:^(STButton *button, NSUInteger idx, BOOL *stop) { button.layer.opacity = 0; CGRect frame = [self frameForMenuAtIndex:idx]; NSInteger rowIndex = idx / columnCount; NSInteger columnIndex = idx % columnCount; CGPoint fromPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2.0, frame.origin.y + (rowCount - rowIndex + 2) * 200 + (STMenuItemImageSize.height + 20) / 2); CGPoint toPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2, frame.origin.y + (STMenuItemImageSize.height + 20) / 2.); double delayInSeconds = rowIndex * columnCount * 0.07; if (!columnIndex) { delayInSeconds += 0.07; } else if (columnIndex == 2) { delayInSeconds += 0.07 * 2; } CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; positionAnimation.fromValue = [NSValue valueWithCGPoint:fromPosition]; positionAnimation.toValue = [NSValue valueWithCGPoint:toPosition]; positionAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.45f:0.6f:0.75f:1.0f]; positionAnimation.duration = 0.35; positionAnimation.beginTime = [button.layer convertTime:CACurrentMediaTime() fromLayer:nil] + delayInSeconds; [positionAnimation setValue:[NSNumber numberWithUnsignedInteger:idx] forKey:@"STMenuPresentAnimationKey"]; positionAnimation.delegate = self; [button.layer addAnimation:positionAnimation forKey:@"riseAnimation"]; }]; } - (void)dropAnimation { NSUInteger columnCount = 3; __block double delayInSeconds; [self.menuItemViews enumerateObjectsUsingBlock:^(UIView *button, NSUInteger idx, BOOL *stop) { button.layer.opacity = 1.0; CGRect frame = [self frameForMenuAtIndex:idx]; NSInteger rowIndex = idx / columnCount; NSInteger columnIndex = idx % columnCount; CGPoint fromPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2.0, frame.origin.y + (STMenuItemImageSize.height + 20) / 2.0); CGPoint toPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2.0, frame.origin.y - (rowIndex + 2) * 200 + (STMenuItemImageSize.height + 20) / 2.0); delayInSeconds = rowIndex * columnCount * 0.07; if (!columnIndex) { delayInSeconds += 0.07; } else if (columnIndex == 2) { delayInSeconds += 0.07 * 2; } CABasicAnimation *positionAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; positionAnimation.fromValue = [NSValue valueWithCGPoint:fromPosition]; positionAnimation.toValue = [NSValue valueWithCGPoint:toPosition]; positionAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.3:0.5f:1.0f:1.0f]; positionAnimation.duration = 0.35; positionAnimation.beginTime = [button.layer convertTime:CACurrentMediaTime() fromLayer:nil] + delayInSeconds; [positionAnimation setValue:[NSNumber numberWithUnsignedInteger:idx] forKey:@"STMenuDismissAnimationKey"]; positionAnimation.delegate = self; [button.layer addAnimation:positionAnimation forKey:@"riseAnimation"]; }]; } - (void)animationDidStart:(CAAnimation *)animation { NSUInteger columnCount = 3; if ([animation valueForKey:@"STMenuPresentAnimationKey"]) { NSUInteger index = [[animation valueForKey:@"STMenuPresentAnimationKey"] unsignedIntegerValue]; UIView *view = self.menuItemViews[index]; CGRect frame = [self frameForMenuAtIndex:index]; CGPoint toPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2.0, frame.origin.y + (STMenuItemImageSize.height + 20) / 2.0); CGFloat toAlpha = 1.0; view.layer.position = toPosition; view.layer.opacity = toAlpha; } else if ([animation valueForKey:@"STMenuDismissAnimationKey"]) { NSUInteger index = [[animation valueForKey:@"STMenuDismissAnimationKey"] unsignedIntegerValue]; NSUInteger rowIndex = index / columnCount; UIView *view = self.menuItemViews[index]; CGRect frame = [self frameForMenuAtIndex:index]; CGPoint toPosition = CGPointMake(frame.origin.x + STMenuItemImageSize.width / 2.0, frame.origin.y - (rowIndex + 2) * 200 + (STMenuItemImageSize.height + 20) / 2.0); view.layer.position = toPosition; } } - (void)panGestureActionFired:(UIPanGestureRecognizer *)sender { static BOOL effected = NO; switch (sender.state) { case UIGestureRecognizerStateBegan: effected = YES; self.dismissButton.highlighted = YES; break; case UIGestureRecognizerStateChanged: if (ABS([sender translationInView:self.blurView].x) > 50 || ABS([sender translationInView:self.blurView].y) > 50) { effected = NO; self.dismissButton.highlighted = NO; } else { self.dismissButton.highlighted = YES; effected = YES; } break; case UIGestureRecognizerStateFailed: case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateCancelled: if (effected) { [self.dismissButton sendActionsForControlEvents:UIControlEventTouchUpInside]; } self.dismissButton.highlighted = NO; break; default: break; } } - (void)tapGestureActionFired:(UITapGestureRecognizer *)sender { switch (sender.state) { case UIGestureRecognizerStateBegan: self.dismissButton.highlighted = YES; break; case UIGestureRecognizerStateChanged: break; case UIGestureRecognizerStateFailed: case UIGestureRecognizerStateEnded: case UIGestureRecognizerStateCancelled: [self.dismissButton sendActionsForControlEvents:UIControlEventTouchUpInside]; self.dismissButton.highlighted = NO; break; default: break; } } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if (touch.view == self.blurView) { self.dismissButton.highlighted = YES; return YES; } return NO; } @end const CGSize STMenuItemImageSize = {75, 75}; ================================================ FILE: STKitDemo/Classes/BaseUI/SideBar/STDLeftViewController.h ================================================ // // STDLeftViewController.h // STKitDemo // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDLeftViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/BaseUI/SideBar/STDLeftViewController.m ================================================ // // STDLeftViewController.m // STKitDemo // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDLeftViewController.h" #import "STDAboutViewController.h" @interface STDLeftViewController () @property(nonatomic, weak) UITableView *tableView; @property(nonatomic, strong) NSArray *dataSource; @end @implementation STDLeftViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.dataSource = @[ @{ @"title" : @"地图", @"image" : @"SideBarNearby" }, @{ @"title" : @"组件", @"image" : @"tab_receipt" }, @{ @"title" : @"服务", @"image" : @"tab_service" }, @{ @"title" : @"我的", @"image" : @"tab_profile" } ]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; CGRect rect = self.view.bounds; UIImageView *headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, rect.size.width, 87)]; headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth; headerView.image = [UIImage imageNamed:@"left_account_header.png"]; headerView.contentMode = UIViewContentModeLeft; [self.view addSubview:headerView]; rect.origin.y += 37; rect.size.height -= 77; UITableView *tableView = [[UITableView alloc] initWithFrame:rect style:UITableViewStylePlain]; tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Identifier"]; tableView.dataSource = self; tableView.delegate = self; tableView.scrollsToTop = NO; [self.view addSubview:tableView]; self.tableView = tableView; STLinkLabel *linkLabel = [[STLinkLabel alloc] initWithFrame:CGRectMake(20, CGRectGetMaxY(rect) + 10, CGRectGetWidth(rect) - 40, 30)]; linkLabel.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; linkLabel.backgroundColor = [UIColor clearColor]; linkLabel.delegate = self; linkLabel.font = [UIFont systemFontOfSize:15]; // NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; linkLabel.text = @"关于STKit Copyright 2014"; [self.view addSubview:linkLabel]; UIView *tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 50)]; UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 280, 49.5)]; nameLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; nameLabel.font = [UIFont boldSystemFontOfSize:18.]; nameLabel.textColor = [UIColor blackColor]; nameLabel.backgroundColor = [UIColor clearColor]; nameLabel.text = @"STKitDemo"; [tableHeaderView addSubview:nameLabel]; UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 49.5, CGRectGetWidth(tableView.frame), 0.5)]; separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth; separatorView.backgroundColor = [UIColor lightGrayColor]; [tableHeaderView addSubview:separatorView]; tableView.tableHeaderView = tableHeaderView; tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)]; [tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionBottom]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataSource.count; } // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with // dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Identifier"]; NSDictionary *information = [self.dataSource objectAtIndex:indexPath.row]; NSString *title = [information valueForKey:@"title"]; NSString *imageName = [information valueForKey:@"image"]; cell.textLabel.text = title; cell.textLabel.textColor = [UIColor st_colorWithRGB:0xACACAC]; cell.textLabel.highlightedTextColor = [UIColor st_colorWithRGB:0xFF7300]; cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@_normal.png", imageName]]; cell.imageView.highlightedImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@_highlighted.png", imageName]]; return cell; } #pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 40.; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { self.st_sideBarController.selectedIndex = indexPath.row; } - (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleDefault; } #pragma mark - STLinkLabelDelegate - (void)linkLabel:(STLinkLabel *)linkLabel didSelectLinkObject:(STLinkObject *)linkObject { if ([linkObject.URL.absoluteString hasSuffix:@"about"]) { STDAboutViewController *aboutViewController = [[STDAboutViewController alloc] init]; aboutViewController.hidesBottomBarWhenPushed = YES; [self.st_sideBarController.st_navigationController pushViewController:aboutViewController animated:YES]; } } @end ================================================ FILE: STKitDemo/Classes/BaseUI/SideBar/STDSideBarController.h ================================================ // // STDSideBarController.h // STKit // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @interface STDSideBarController : STSideBarController @end ================================================ FILE: STKitDemo/Classes/BaseUI/SideBar/STDSideBarController.m ================================================ // // STDSideBarController.m // STKitDemo // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDSideBarController.h" #import "STARootViewController.h" #import "STDMoreViewController.h" #import "STDMapViewController.h" #import "STDemoViewController.h" #import "STDServiceViewController.h" @interface STDSideBarController () @end @implementation STDSideBarController - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { self = [super initWithRootViewController:rootViewController]; if (self) { STDMapViewController *mapViewController = STDMapViewController.new; STNavigationController *mapNavigationController = [[STNavigationController alloc] initWithRootViewController:mapViewController]; STDemoViewController *controlsViewController = [[STDemoViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *controlsNavigationController = [[STNavigationController alloc] initWithRootViewController:controlsViewController]; STDServiceViewController *serviceViewController = [[STDServiceViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *serviceNavigationController = [[STNavigationController alloc] initWithRootViewController:serviceViewController]; STDMoreViewController *moreViewController = [[STDMoreViewController alloc] initWithStyle:UITableViewStyleGrouped]; STNavigationController *moreNavigationController = [[STNavigationController alloc] initWithRootViewController:moreViewController]; self.viewControllers = @[mapNavigationController, controlsNavigationController, serviceNavigationController, moreNavigationController]; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDCardViewController.h ================================================ // // STDCardViewController.h // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDFeedViewController.h" /// 明星片 @interface STDCardViewController : STDFeedViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDCardViewController.m ================================================ // // STDCardViewController.m // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDCardViewController.h" @interface STDCardViewController () @property (nonatomic, strong) STHTTPNetwork *network; @end @implementation STDCardViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.network = [[STHTTPNetwork alloc] init]; } return self; } - (void) viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"明信片"; } - (void) loadDataWithPage:(NSInteger)page size:(NSInteger)size completionHandler:(STDFeedLoadHandler)completionHandler { NSDictionary * parameters = @{@"page":@(page), @"size":@(size)}; NSString *URLString = @"http://www.lovecard.sinaapp.com/open/photo/list/"; STHTTPOperation *operation = [STHTTPOperation operationWithURLString:URLString parameters:parameters]; [self.network sendHTTPOperation:operation completionHandler:^(STHTTPOperation *operation, id response, NSError *error) { if (!error) { NSMutableArray * result = [NSMutableArray arrayWithCapacity:2]; NSArray * array = [response objectForKey:@"photos"]; BOOL hasMore = [[response objectForKey:@"more"] boolValue] && array.count > 0; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { STDFeedItem * feedItem = [[STDFeedItem alloc] initWithDictionary:obj]; [result addObject:feedItem]; }]; if (completionHandler) { completionHandler([result copy], hasMore, nil); } } else { if (completionHandler) { completionHandler(nil, NO, error); } } }]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedCell.h ================================================ // // STDFeedCell.h // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import "STDFeedItem.h" @interface STDFeedCell : UICollectionViewCell @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, strong) STLabel * titleLabel; @property (nonatomic, strong) STDFeedItem * feedItem; - (void) reloadUI; + (CGFloat) heightForCollectionCellWithFeedItem:(STDFeedItem *) feedItem constrainedToWidth:(CGFloat) width; @end extern UIEdgeInsets const STDFeedCellContentInset; ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedCell.m ================================================ // // STDFeedCell.m // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDFeedCell.h" #import "STDFeedImageView.h" @interface STDFeedHotView : UIView @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, strong) UILabel * textLabel; @end @implementation STDFeedHotView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 14, 20)]; self.imageView.contentMode = UIViewContentModeScaleAspectFit; self.imageView.image = [UIImage imageNamed:@"feed_hot_icon"]; [self addSubview:self.imageView]; self.textLabel = [[UILabel alloc] initWithFrame:CGRectMake(18, 4, 30, 16)]; self.textLabel.backgroundColor = [UIColor clearColor]; self.textLabel.textColor = [UIColor st_colorWithRGB: 0xFF7300]; self.textLabel.font = [UIFont systemFontOfSize:14.]; self.textLabel.text = @"Hot"; [self addSubview:self.textLabel]; } return self; } @end const CGSize STDFeedCellDefaultSize = {50, 70}; const CGFloat STDFeedCellAccessoryHeight = 30; const UIEdgeInsets STDFeedCellTitleContentInset = {5,5,10,5}; @interface STDFeedCell () @property (nonatomic, strong) UIImageView * backgroundImageView; @property (nonatomic, strong) UIView * containerView; @property (nonatomic, strong) UIView * accessoryView; @property (nonatomic, strong) STDFeedHotView * hotView; @end @implementation STDFeedCell - (instancetype) initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.frame = CGRectMake(0, 0, STDFeedCellDefaultSize.width, STDFeedCellDefaultSize.height); self.contentView.frame = self.bounds; self.backgroundColor = [UIColor st_colorWithRGB:0xCCCCCC]; self.backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(STDFeedCellContentInset.left, STDFeedCellContentInset.top, STDFeedCellDefaultSize.width - (STDFeedCellContentInset.left + STDFeedCellContentInset.right), STDFeedCellDefaultSize.height - (STDFeedCellContentInset.top + STDFeedCellContentInset.bottom))]; self.backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.backgroundImageView.image = [[UIImage imageNamed:@"feed_cell_background"] resizableImageWithCapInsets:UIEdgeInsetsMake(20, 70, 20, 70) resizingMode:UIImageResizingModeStretch]; self.backgroundImageView.userInteractionEnabled = YES; [self.contentView addSubview:self.backgroundImageView]; self.imageView = [[STDFeedImageView alloc] initWithFrame:CGRectZero]; self.imageView.contentMode = UIViewContentModeScaleAspectFill; self.imageView.clipsToBounds = YES; self.imageView.userInteractionEnabled = YES; self.imageView.st_placeholderImage = [UIImage imageNamed:@"product_default"]; [self.backgroundImageView addSubview:self.imageView]; self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 40, 40)]; self.containerView.backgroundColor = [UIColor clearColor]; [self.backgroundImageView addSubview:self.containerView]; self.titleLabel = [[STLabel alloc] initWithFrame:CGRectZero]; self.titleLabel.verticalAlignment = STVerticalAlignmentTop; self.titleLabel.backgroundColor = [UIColor clearColor]; self.titleLabel.font = [UIFont systemFontOfSize:14]; self.titleLabel.textColor = [UIColor darkGrayColor]; self.titleLabel.numberOfLines = 0; self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; [self.containerView addSubview:self.titleLabel]; self.accessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, STDFeedCellAccessoryHeight)]; self.accessoryView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; [self.containerView addSubview:self.accessoryView]; UIView * separatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, STOnePixel())]; separatorView.autoresizingMask = UIViewAutoresizingFlexibleWidth; separatorView.backgroundColor = [UIColor st_colorWithRGB:0xdddddd]; [self.accessoryView addSubview:separatorView]; self.hotView = [[STDFeedHotView alloc] initWithFrame:CGRectMake(5, 2, 60, STDFeedCellAccessoryHeight)]; [self.accessoryView addSubview:self.hotView]; UIImageView * coverView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 60)]; coverView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; coverView.image = [[UIImage imageNamed:@"feed_cell_border"] resizableImageWithCapInsets:UIEdgeInsetsMake(15, 15, 15, 15) resizingMode:UIImageResizingModeStretch]; coverView.userInteractionEnabled = NO; [self.backgroundImageView addSubview:coverView]; } return self; } - (void) setFeedItem:(STDFeedItem *)feedItem { if (_feedItem != feedItem) { [self.imageView st_setImageWithURLString:feedItem.thumbURLString]; self.titleLabel.text = feedItem.title; _feedItem = feedItem; } [self reloadUI]; } - (void) reloadUI { CGFloat width = CGRectGetWidth(self.frame) - STDFeedCellContentInset.left - STDFeedCellContentInset.right; CGFloat imageHeight = self.feedItem.height * width / self.feedItem.width; self.imageView.frame = CGRectMake(0, 0, width, imageHeight); self.containerView.frame = CGRectMake(0, CGRectGetMaxY(self.imageView.frame), width, CGRectGetHeight(self.frame) - CGRectGetMaxY(self.imageView.frame)); if (self.feedItem.title.length > 0) { self.titleLabel.frame = CGRectMake(STDFeedCellTitleContentInset.left, STDFeedCellTitleContentInset.top, CGRectGetWidth(self.containerView.frame) - STDFeedCellTitleContentInset.left - STDFeedCellTitleContentInset.right, CGRectGetHeight(self.containerView.frame) - STDFeedCellAccessoryHeight - STDFeedCellTitleContentInset.top - STDFeedCellTitleContentInset.bottom); } } + (CGFloat) heightForCollectionCellWithFeedItem:(STDFeedItem *) feedItem constrainedToWidth:(CGFloat) _width { if (feedItem.width * feedItem.height == 0) { return 0; } CGFloat width = _width - STDFeedCellContentInset.left - STDFeedCellContentInset.right; CGFloat height = feedItem.height * width / feedItem.width + STDFeedCellContentInset.top + STDFeedCellContentInset.bottom; if (feedItem.title.length > 0) { CGFloat titleWidth = width - (STDFeedCellTitleContentInset.left + STDFeedCellTitleContentInset.right); CGFloat titleHeight = [feedItem.title st_heightWithFont:[UIFont systemFontOfSize:14] constrainedToWidth:titleWidth]; height += (titleHeight + STDFeedCellTitleContentInset.top + STDFeedCellTitleContentInset.bottom); } height += STDFeedCellAccessoryHeight; return height; } @end UIEdgeInsets const STDFeedCellContentInset = {5, 5, 5, 5}; ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedImageView.h ================================================ // // STDFeedImageView.h // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STDFeedImageView : UIImageView @property (nonatomic, strong, readonly) UIView * selectedView; @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedImageView.m ================================================ // // STDFeedImageView.m // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDFeedImageView.h" #import @interface STDFeedImageView () @property (nonatomic, strong) UIView * selectedView; @end @implementation STDFeedImageView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.selectedView = [[UIView alloc] initWithFrame:self.bounds]; self.selectedView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.selectedView.hidden = YES; self.selectedView.backgroundColor = [UIColor st_colorWithRGB:0x0 alpha:0.5]; [self addSubview:self.selectedView]; } return self; } - (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; self.selectedView.hidden = NO; } - (void) touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; self.selectedView.hidden = YES; } - (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; self.selectedView.hidden = YES; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedItem.h ================================================ // // STDFeedItem.h // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STDFeedItem : STObject @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *thumbURLString; @property (nonatomic, copy) NSString *imageURLString; @property (nonatomic, assign) CGFloat width; @property (nonatomic, assign) CGFloat height; // 评分 @property (nonatomic, assign) CGFloat rate; - (STImageItem *)imageItem; @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedItem.m ================================================ // // STDFeedItem.m // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDFeedItem.h" @implementation STDFeedItem + (NSDictionary *) relationship { return @{@"thumbURLString":@"thumb", @"imageURLString":@"photo"}; } - (STImageItem *) imageItem { STImageItem * imageItem = [[STImageItem alloc] init]; imageItem.imageURLString = self.imageURLString; imageItem.thumbURLString = self.thumbURLString; return imageItem; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedViewController.h ================================================ // // STDFeedViewController.h // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" #import "STDFeedItem.h" typedef void(^ STDFeedLoadHandler) (NSArray * feeds, BOOL hasMore, NSError * error); @interface STDFeedViewController : STDViewController @property (nonatomic, assign) BOOL automaticallyFetchRemoteData; @property (nonatomic, strong) UICollectionView * collectionView; @property (nonatomic, weak, readonly) STRefreshControl * refreshControl; @property (nonatomic, strong, readonly) NSMutableArray * feeds; @property (nonatomic, assign, readonly) NSTimeInterval previousRequestTime; @property (nonatomic, assign, readonly) BOOL loading; - (void) loadDataFromCacheWithHandler:(STDFeedLoadHandler) completionHandler; - (void) loadDataWithPage:(NSInteger) page size:(NSInteger) size completionHandler:(STDFeedLoadHandler) completionHandler; - (void) saveDataToCache:(NSArray *) feeds; - (NSString *) cacheIdentifier; @end extern NSInteger const STDFeedLoadPageSize; ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDFeedViewController.m ================================================ // // STDFeedViewController.m // STKitDemo // // Created by SunJiangting on 14-9-26. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDFeedViewController.h" #import "STDFeedCell.h" #import "STDRefreshControl.h" @interface STDFeedViewController () @property (nonatomic, assign) NSInteger page; @property (nonatomic, weak) STRefreshControl * refreshControl; @property (nonatomic, strong) NSMutableArray * feeds; @property (nonatomic, assign) BOOL hasMore; @property (nonatomic, assign) NSTimeInterval previousRequestTime; @property (nonatomic, strong) STScrollDirector * collectionDirector; @end @implementation STDFeedViewController - (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.collectionDirector = [[STScrollDirector alloc] init]; STDRefreshControl *refreshControl = [[STDRefreshControl alloc] initWithFrame:CGRectMake(0, 0, 200, 76)]; refreshControl.threshold = 76; // self.collectionDirector.refreshControl = refreshControl; [self.collectionDirector setTitle:@"加载更多" forState:STScrollDirectorStatePaginationNormal]; [self.collectionDirector setTitle:@"正在加载更多" forState:STScrollDirectorStatePaginationLoading]; [self.collectionDirector setTitle:@"重新加载" forState:STScrollDirectorStatePaginationFailed]; [self.collectionDirector setTitle:@"没有更多了" forState:STScrollDirectorStatePaginationReachedEnd]; self.feeds = [NSMutableArray arrayWithCapacity:5]; self.automaticallyFetchRemoteData = YES; self.hidesBottomBarWhenPushed = YES; } return self; } - (void) viewDidLoad { [super viewDidLoad]; [self loadDataFromCacheWithHandler:^(NSArray *feeds, BOOL hasMore, NSError *error) { [self.feeds addObjectsFromArray:feeds]; }]; STCollectionViewFlowLayout * collectionViewFlowLayout = [[STCollectionViewFlowLayout alloc] init]; collectionViewFlowLayout.minimumInteritemSpacing = 0; collectionViewFlowLayout.minimumLineSpacing = 0; collectionViewFlowLayout.numberOfColumns = [self preferredNumberOfColumnsWithWidth:CGRectGetWidth(self.view.frame)]; UICollectionView * collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:collectionViewFlowLayout]; collectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; collectionView.backgroundView = nil; collectionView.backgroundColor = [UIColor st_colorWithRGB:0xCCCCCC]; collectionView.dataSource = self; collectionView.delegate = self; [collectionView registerClass:[STDFeedCell class] forCellWithReuseIdentifier:@"Identifier"]; [self.view addSubview:collectionView]; self.collectionView = collectionView; self.collectionDirector.scrollView = collectionView; [self.collectionDirector.refreshControl addTarget:self action:@selector(refreshControlActionFired:) forControlEvents:UIControlEventValueChanged]; [self.collectionDirector.paginationControl addTarget:self action:@selector(paginationControlActionFired:) forControlEvents:UIControlEventValueChanged]; self.refreshControl = self.collectionDirector.refreshControl; [self.refreshControl beginRefreshing]; } - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970]; // if (((timeInterval - self.previousRequestTime) > 300 || self.feeds.count == 0) && !self.refreshControl.isRefreshing && self.automaticallyFetchRemoteData) { // [self.refreshControl beginRefreshing]; // } } - (void)GIFGeneratorActionFired:(id) sender { NSInteger maximumCount = 5; STGIFGenerator *generator = [[STGIFGenerator alloc] init]; [self.feeds enumerateObjectsUsingBlock:^(STDFeedItem * obj, NSUInteger idx, BOOL *stop) { UIImage *image = [STImageCache cachedImageForKey:obj.thumbURLString]; [generator appendImage:image duration:1]; if (idx == maximumCount) { *stop = YES; } }]; [generator startGeneratorWithPath:nil completionHandler:^(NSString *path) { NSLog(@"%@", path); }]; } - (void) refreshControlActionFired:(id) sender { self.page = 0; __weak STDFeedViewController * weakSelf = self; [self loadDataWithPage:0 size:STDFeedLoadPageSize completionHandler:^(NSArray *feeds, BOOL hasMore, NSError *error) { if (!error) { [weakSelf.feeds removeAllObjects]; [weakSelf.feeds addObjectsFromArray:feeds]; weakSelf.hasMore = hasMore; [weakSelf reloadCollectionFooterView]; weakSelf.previousRequestTime = [[NSDate date] timeIntervalSince1970]; NSString * cacheKey = [NSString stringWithFormat:@"%@-LastRequest", [self cacheIdentifier]].st_md5String; [[STPersistence standardPersistence] setValue:@(weakSelf.previousRequestTime) forKey:cacheKey]; [weakSelf.collectionView reloadData]; [weakSelf saveDataToCache:feeds]; } [weakSelf.collectionDirector.refreshControl endRefreshing]; }]; } - (void) saveDataToCache:(NSArray *) feeds { NSMutableArray * result = [NSMutableArray arrayWithCapacity:5]; [feeds enumerateObjectsUsingBlock:^(STDFeedItem * obj, NSUInteger idx, BOOL *stop) { [result addObject:[obj toDictionary]]; }]; NSString * cacheKey = [NSString stringWithFormat:@"%@-CachedData", [self cacheIdentifier]].st_md5String; [[STPersistence cachePersistenceWithSubpath:@"FeedCache"] setValue:result forKey:cacheKey]; } - (void) reloadCollectionFooterView { if (self.hasMore) { self.collectionDirector.paginationControl.paginationState = STPaginationControlStateNormal; } else { self.collectionDirector.paginationControl.paginationState = STPaginationControlStateReachedEnd; } self.collectionView.collectionFooterView = self.collectionDirector.paginationControl; } - (void) paginationControlActionFired:(id) sender { self.page ++; __weak STDFeedViewController * weakSelf = self; [self loadDataWithPage:self.page size:STDFeedLoadPageSize completionHandler:^(NSArray *feeds, BOOL hasMore, NSError *error) { if (!error) { [weakSelf.feeds addObjectsFromArray:feeds]; weakSelf.hasMore = hasMore; [weakSelf reloadCollectionFooterView]; [weakSelf.collectionView reloadData]; } }]; } - (void)loadDataFromCacheWithHandler:(STDFeedLoadHandler) completionHandler { NSMutableArray * result = [NSMutableArray arrayWithCapacity:5]; NSString * cacheKey = [NSString stringWithFormat:@"%@-CachedData", [self cacheIdentifier]].st_md5String; NSArray * cachedData = [[STPersistence cachePersistenceWithSubpath:@"FeedCache"] valueForKey:cacheKey]; if ([cachedData isKindOfClass:[NSArray class]]) { [cachedData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { STDFeedItem * feedItem = [[STDFeedItem alloc] initWithDictionary:obj]; [result addObject:feedItem]; }]; } if (completionHandler) { completionHandler(result, NO,nil); } } - (void) loadDataWithPage:(NSInteger) page size:(NSInteger) size completionHandler:(STDFeedLoadHandler) completionHandler { completionHandler(nil, NO,nil); } #pragma mark - UICollectionViewDataSource - (NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1; } - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return self.feeds.count; } - (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { STDFeedCell * collectionCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Identifier" forIndexPath:indexPath]; collectionCell.feedItem = self.feeds[indexPath.row]; return collectionCell; } - (void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { NSMutableArray * images = [NSMutableArray arrayWithCapacity:2]; [self.feeds enumerateObjectsUsingBlock:^(STDFeedItem * obj, NSUInteger idx, BOOL *stop) { [images addObject:obj.imageItem]; }]; STImagePresent * imagePresent = [[STImagePresent alloc] initWithImages:images]; imagePresent.delegate = self; [imagePresent presentImageAtIndex:indexPath.row animated:YES]; } #pragma mark - STCollectionViewDelegateFlowLayout - (CGSize)collectionView:(UICollectionView *)collectionView layout:(STCollectionViewFlowLayout *) collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { STDFeedItem * feedItem = self.feeds[indexPath.row]; NSInteger numberOfColumns = collectionViewLayout.numberOfColumns; if (numberOfColumns * feedItem.width * feedItem.height == 0) { return CGSizeZero; } CGFloat width = CGRectGetWidth(collectionView.bounds) / numberOfColumns; CGFloat height = [STDFeedCell heightForCollectionCellWithFeedItem:feedItem constrainedToWidth:width]; return CGSizeMake(width, height); } #pragma mark - STImagePresent - (void) imagePresent:(STImagePresent *) imagePresent didPresentImageAtIndex:(NSInteger) index { NSIndexPath * indexPath = [NSIndexPath indexPathForItem:index inSection:0]; if (![self.collectionView cellForItemAtIndexPath:indexPath]) { [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO]; } } - (UIImageView *) imagePresent:(STImagePresent *) imagePresent imageViewForImageAtIndex:(NSInteger) index { NSIndexPath * indexPath = [NSIndexPath indexPathForItem:index inSection:0]; STDFeedCell * collectionViewCell = (STDFeedCell *)[self.collectionView cellForItemAtIndexPath:indexPath]; return collectionViewCell.imageView; } #pragma mark - Private - (void) reloadCollectionFooterView:(UIView *) footerView { self.collectionView.collectionFooterView = footerView; } - (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; STCollectionViewFlowLayout * flowLayout = (STCollectionViewFlowLayout *) self.collectionView.collectionViewLayout; flowLayout.numberOfColumns = [self preferredNumberOfColumnsWithWidth:CGRectGetWidth(self.view.frame)]; [self.collectionView reloadData]; } - (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; STCollectionViewFlowLayout * flowLayout = (STCollectionViewFlowLayout *) self.collectionView.collectionViewLayout; flowLayout.numberOfColumns = [self preferredNumberOfColumnsWithWidth:size.width]; [self.collectionView reloadData]; } - (NSInteger)preferredNumberOfColumnsWithWidth:(CGFloat) width { if (width == 320) { return 2; } if (width == 375) { return 3; } return width / 160; } - (NSString *)cacheIdentifier { return NSStringFromClass([self class]); } - (NSTimeInterval)previousRequestTime { if (_previousRequestTime == 0) { NSString * cacheKey = [NSString stringWithFormat:@"%@-LastRequest", [self cacheIdentifier]].st_md5String; _previousRequestTime = [[[STPersistence standardPersistence] valueForKey:cacheKey] doubleValue]; } return _previousRequestTime; } @end NSInteger const STDFeedLoadPageSize = 50; ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDownloadViewController.h ================================================ // // STDownloadViewController.h // STKitDemo // // Created by SunJiangting on 14-3-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDownloadViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/Image/STDownloadViewController.m ================================================ // // STDownloadViewController.m // STKitDemo // // Created by SunJiangting on 14-3-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDownloadViewController.h" #import "STAlertView.h" @interface STDownloadViewController () @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, strong) STRoundProgressView * roundProgressView; @property (nonatomic, strong) NSString * thumbURL; @property (nonatomic, strong) NSString * imageURL; @end @implementation STDownloadViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.hidesBottomBarWhenPushed = YES; self.thumbURL = @"http://lovecard-photo.stor.sinaapp.com/D294D8DFA381405970FA52E579E8A7B2.jpg"; self.imageURL = @"http://lovecard-photo.stor.sinaapp.com/735F748E2F2482591C1DFE1351E622E9.jpg"; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"图片下载"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"弹框" target:self action:@selector(alertActionFired:)]; UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(self.view.width / 2 - 120, 20, 240, 40)]; containerView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self.view addSubview:containerView]; self.edgesForExtendedLayout = (UIRectEdgeLeft | UIRectEdgeRight); UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0, 0, 80, 40); [button addTarget:self action:@selector(downloadImage:) forControlEvents:UIControlEventTouchUpInside]; [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [button setTitle:@"点我下载" forState:UIControlStateNormal]; [containerView addSubview:button]; UIButton * button1 = [UIButton buttonWithType:UIButtonTypeCustom]; button1.frame = CGRectMake(160, 0, 80, 40); [button1 setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [button1 setTitle:@"清除缓存" forState:UIControlStateNormal]; [button1 addTarget:self action:@selector(cleanCache:) forControlEvents:UIControlEventTouchUpInside]; [containerView addSubview:button1]; self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.width / 2 - 60, 80, 120, 120)]; self.imageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; self.imageView.contentMode = UIViewContentModeScaleAspectFit; self.imageView.userInteractionEnabled = YES; [self.imageView st_addTouchTarget:self action:@selector(seeBigImage:)]; [self.view addSubview:self.imageView]; self.roundProgressView = [[STRoundProgressView alloc] initWithFrame:CGRectMake(0, 0, 35, 35)]; self.roundProgressView.center = self.imageView.center; self.roundProgressView.hidden = YES; [self.imageView addSubview:self.roundProgressView]; } - (void)alertActionFired:(id)sender { STAlertView * alertView = [[STAlertView alloc] initWithMenuTitles:@"First", @"Second", @"Third", nil]; __unused NSInteger result = [alertView showInView:self.view animated:YES]; } - (void) cleanCache:(id) sender { [STImageCache removeCacheImageForKey:self.thumbURL]; [STImageCache removeCacheImageForKey:self.imageURL]; self.imageView.image = nil; } - (void) seeBigImage:(id) sender { if (self.imageView.image) { [STImagePresent presentImageView:self.imageView hdImageURL:self.imageURL]; } } - (void) downloadImage:(id) sender { NSString * imageURL = self.thumbURL; if ([STImageCache hasCachedImageForKey:imageURL]) { __weak STDownloadViewController * weakSelf = self; [self.imageView st_setImageWithURLString:imageURL finishedHandler:^(UIImage *image, NSString * URLString, BOOL usingCache, NSError *error) { weakSelf.imageView.image = image; }]; return; } __weak STDownloadViewController * weakSelf = self; self.roundProgressView.hidden = NO; self.roundProgressView.center = CGPointMake(self.imageView.bounds.size.width / 2, self.imageView.bounds.size.height / 2); [self.imageView st_setImageWithURLString:imageURL progressHandler:^(CGFloat completion) { weakSelf.roundProgressView.completion = completion; } finishedHandler:^(UIImage *image, NSString * URLString, BOOL usingCache, NSError *error) { weakSelf.roundProgressView.hidden = YES; weakSelf.imageView.image = image; }]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDImageBlurViewController.h ================================================ // // STDImageBlurViewController.h // STKitDemo // // Created by SunJiangting on 14-10-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDImageBlurViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDImageBlurViewController.m ================================================ // // STDImageBlurViewController.m // STKitDemo // // Created by SunJiangting on 14-10-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDImageBlurViewController.h" #import "MZCroppableView.h" #import "UIBezierPath-Points.h" @interface STDImageBlurViewController () @property(nonatomic, strong) UIView *containerView; @property(nonatomic, strong) UIImageView *backgroundImageView; @property(nonatomic, strong) MZCroppableView *croppableView; @property(nonatomic, strong) UIImageView *coverImageView; @end @implementation STDImageBlurViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.st_interactivePopTransitionOffset = 15; self.customizeEdgeOffset = NO; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.edgesForExtendedLayout = UIRectEdgeNone; self.navigationItem.title = @"图片裁剪"; UIView *containerView = [[UIView alloc] initWithFrame:self.view.bounds]; containerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:containerView]; self.containerView = containerView; UIImage *backgroundImage = [UIImage imageNamed:@"LaunchImage"]; UIImageView *backgroundImageView = [[UIImageView alloc] initWithFrame:containerView.bounds]; backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; backgroundImageView.image = backgroundImage; [containerView addSubview:backgroundImageView]; self.backgroundImageView = backgroundImageView; self.coverImageView = [[UIImageView alloc] initWithFrame:backgroundImageView.frame]; self.coverImageView.autoresizingMask = backgroundImageView.autoresizingMask; [containerView addSubview:self.coverImageView]; self.coverImageView.backgroundColor = [UIColor clearColor]; self.coverImageView.hidden = YES; MZCroppableView *croppableView = [[MZCroppableView alloc] initWithImageView:backgroundImageView]; croppableView.frame = containerView.bounds; croppableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [containerView addSubview:croppableView]; self.croppableView = croppableView; UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.height - 44, self.view.width, 44)]; UIBarButtonItem *resetItem = [[UIBarButtonItem alloc] initWithTitle:@"重置" style:UIBarButtonItemStylePlain target:self action:@selector(resetActionFired:)]; UIBarButtonItem *flexibleItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL]; UIBarButtonItem *finishItem = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(finishActionFired:)]; toolbar.items = @[ resetItem, flexibleItem, finishItem ]; toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; [self.view addSubview:toolbar]; containerView.bottom = toolbar.top; } - (void)resetActionFired:(id)sender { [self.croppableView removeFromSuperview]; MZCroppableView *croppableView = [[MZCroppableView alloc] initWithImageView:self.backgroundImageView]; croppableView.frame = self.containerView.bounds; croppableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.containerView addSubview:croppableView]; self.croppableView = croppableView; self.coverImageView.hidden = YES; } - (void)finishActionFired:(id)sender { NSArray *points = [self.croppableView.croppingPath points]; if (!points.count) { [[[UIAlertView alloc]initWithTitle:@"摸我!" message:@"尝试用手在图片上随便摸两下" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil] show]; return; } CGSize imageViewSize = self.backgroundImageView.size; CGSize imageSize = self.backgroundImageView.image.size; UIBezierPath *aPath = [UIBezierPath bezierPath]; { // Set the starting point of the shape. CGPoint p1 = [MZCroppableView convertCGPoint:CGPointFromString(points[0]) fromRect1:imageViewSize toRect2:imageSize]; [aPath moveToPoint:p1]; for (uint i = 1; i < points.count; i++) { CGPoint p = [MZCroppableView convertCGPoint:CGPointFromString(points[i]) fromRect1:imageViewSize toRect2:imageSize]; [aPath addLineToPoint:p]; } [aPath closePath]; } UIImage *blurImage = [self.backgroundImageView.image st_blurImageWithRadius:20. tintColor:nil saturationDeltaFactor:1.3]; UIGraphicsBeginImageContextWithOptions(blurImage.size, NO, [UIScreen mainScreen].scale); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(0, blurImage.size.width, blurImage.size.height, 8, blurImage.size.width * 4, colorSpace, (CGBitmapInfo)kCGImageAlphaPremultipliedLast); UIGraphicsPushContext(context); CGContextDrawImage(context, CGRectMake(0, 0, blurImage.size.width, blurImage.size.height), blurImage.CGImage); CGContextSetBlendMode(context, (CGBlendMode)kCGBlendModeClear); CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor); CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0 green:0 blue:0 alpha:0].CGColor); CGContextAddPath(context, aPath.CGPath); CGContextFillPath(context); CGImageRef cgImage = CGBitmapContextCreateImage(context); UIGraphicsEndImageContext(); UIGraphicsPopContext(); [self.croppableView removeFromSuperview]; self.coverImageView.hidden = NO; self.coverImageView.image = [UIImage imageWithCGImage:cgImage]; CFRelease(cgImage); CFRelease(context); CFRelease(colorSpace); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDNavigationTestViewController.h ================================================ // // STDNavigationTestViewController.h // STKitDemo // // Created by SunJiangting on 14-8-25. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTextTableViewController.h" @interface STDNavigationTestViewController : STDTextTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDNavigationTestViewController.m ================================================ // // STDNavigationTestViewController.m // STKitDemo // // Created by SunJiangting on 14-8-25. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDNavigationTestViewController.h" @interface STDNavigationTestViewController () @property (nonatomic, strong) NSArray *dataSource; @end @implementation STDNavigationTestViewController @dynamic dataSource; - (void)dealloc { } - (instancetype) initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { self.hidesBottomBarWhenPushed = YES; NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:2]; STDTableViewCellItem *item00 = [[STDTableViewCellItem alloc] initWithTitle:@"Push一个有导航栏的" target:self action:@selector(_pushNHNBHSActionFired)]; STDTableViewCellItem *item01 = [[STDTableViewCellItem alloc] initWithTitle:@"Push一个没有导航栏的" target:self action:@selector(_pushNHYBHSActionFired)]; STDTableViewCellItem *item02 = [[STDTableViewCellItem alloc] initWithTitle:@"Push一个有TabBar的" target:self action:@selector(_pushNHSBHNActionFired)]; STDTableViewCellItem *item03 = [[STDTableViewCellItem alloc] initWithTitle:@"Push一个没有TabBar的" target:self action:@selector(_pushNHSBHYActionFired)]; STDTableViewSectionItem *section0 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"从屏幕最左侧右滑拖动可以返回,支持iOS6。" items:@[item00, item01, item02, item03]]; [dataSource addObject:section0]; STDTableViewCellItem *item10 = [[STDTableViewCellItem alloc] initWithTitle:@"PopViewController" target:self action:@selector(_popViewControllerActionFired)]; STDTableViewCellItem *item11 = [[STDTableViewCellItem alloc] initWithTitle:@"PopToRootViewController" target:self action:@selector(_popToRootViewControllerActionFired)]; STDTableViewSectionItem *section1 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"PopViewController" items:@[ item10, item11]]; [dataSource addObject:section1]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"测试导航"; self.scrollDirector.refreshControl.enabled = NO; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Identifier"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)_popViewControllerActionFired { [self.st_navigationController popViewControllerAnimated:YES]; } - (void)_popToRootViewControllerActionFired { [self.st_navigationController popToRootViewControllerAnimated:YES]; } - (void)_pushNHNBHSActionFired { STDNavigationTestViewController * viewController = [[STDNavigationTestViewController alloc] initWithStyle:UITableViewStyleGrouped]; viewController.st_navigationBarHidden = NO; viewController.hidesBottomBarWhenPushed = self.hidesBottomBarWhenPushed; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_pushNHYBHSActionFired { STDNavigationTestViewController * viewController = [[STDNavigationTestViewController alloc] initWithStyle:UITableViewStyleGrouped]; viewController.st_navigationBarHidden = YES; viewController.hidesBottomBarWhenPushed = self.hidesBottomBarWhenPushed; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_pushNHSBHNActionFired { STDNavigationTestViewController * viewController = [[STDNavigationTestViewController alloc] initWithStyle:UITableViewStyleGrouped]; viewController.st_navigationBarHidden = self.st_navigationBarHidden; viewController.hidesBottomBarWhenPushed = NO; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_pushNHSBHYActionFired { STDNavigationTestViewController * viewController = [[STDNavigationTestViewController alloc] initWithStyle:UITableViewStyleGrouped]; viewController.st_navigationBarHidden = self.st_navigationBarHidden; viewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:viewController animated:YES]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDScrollViewController.h ================================================ // // STDScrollViewController.h // STKitDemo // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDScrollViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDScrollViewController.m ================================================ // // STDScrollViewController.m // STKitDemo // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDScrollViewController.h" @interface STDScrollView : UIView @property (nonatomic) CGSize contentSize; @end @implementation STDScrollView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(_panGestureActionFired:)]; [self addGestureRecognizer:panGestureRecognizer]; if (self.contentSize.width * self.contentSize.height == 0) { self.contentSize = frame.size; } } return self; } - (void)_panGestureActionFired:(UIPanGestureRecognizer *)panGestureRecognizer { static CGPoint panStartPoint; static CGRect bounds; if (panGestureRecognizer.state == UIGestureRecognizerStateBegan) { panStartPoint = [panGestureRecognizer locationInView:self]; bounds = self.bounds; } if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) { CGPoint location = [panGestureRecognizer locationInView:self]; CGPoint offset = CGPointMake(location.x - panStartPoint.x, location.y - panStartPoint.y); bounds.origin.x -= offset.x; bounds.origin.y -= offset.y; self.bounds = bounds; } } - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer { CGPoint velocity = [gestureRecognizer velocityInView:self]; return ABS(velocity.x) < ABS(velocity.y); } @end @implementation STDScrollViewController - (void)viewDidLoad { [super viewDidLoad]; self.edgesForExtendedLayout = UIRectEdgeNone; STDScrollView *scrollView = [[STDScrollView alloc] initWithFrame:self.view.bounds]; scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:scrollView]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.backgroundColor = [UIColor redColor]; button.frame = CGRectMake(0, 0, 320, 40); [scrollView addSubview:button]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDemoViewController.h ================================================ // // STDemoViewController.h // STKitDemo // // Created by SunJiangting on 14-2-20. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTextTableViewController.h" @interface STDemoViewController : STDTextTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/STDemoViewController.m ================================================ // // STDemoViewController.m // STKitDemo // // Created by SunJiangting on 14-2-20. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDemoViewController.h" #import "STDTextViewController.h" #import "STDLinkViewController.h" #import "STDNavigationTestViewController.h" #import "STDownloadViewController.h" #import #import "STDCardViewController.h" #import "STDImageBlurViewController.h" #import "STDScrollViewController.h" @interface STDemoViewController () @property(nonatomic, strong) NSMutableArray *dataSource; @property(nonatomic, strong) STNotificationWindow *notificationWindow; @property(nonatomic, strong) STSearchDisplayController *searchController; @end @implementation STDemoViewController @dynamic dataSource; - (id)initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { // Custom initialization NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:2]; self.clearsSelectionOnViewWillAppear = YES; STDTableViewCellItem *item00 = [[STDTableViewCellItem alloc] initWithTitle:@"导航适配" target:self action:@selector(testNavigationActionFired)]; STDTableViewSectionItem *section0 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"包含对导航的一些适配,主要针对于一些NavigationBarHidden时,push或者pop的情况" items:@[ item00 ]]; [dataSource addObject:section0]; STDTableViewCellItem *item10 = [[STDTableViewCellItem alloc] initWithTitle:@"查看大图" target:self action:@selector(imageDownloadActionFired)]; STDTableViewCellItem *item11 = [[STDTableViewCellItem alloc] initWithTitle:@"图片加载" target:self action:@selector(imageCardActionFired)]; STDTableViewCellItem *item12 = [[STDTableViewCellItem alloc] initWithTitle:@"图片选择" target:self action:@selector(imagePickerActionFired)]; STDTableViewCellItem *item13 = [[STDTableViewCellItem alloc] initWithTitle:@"图片打码" target:self action:@selector(imageBlurActionFired)]; STDTableViewSectionItem *section1 = [[STDTableViewSectionItem alloc] initWithSectionTitle: @"以下为一些对图片封装, 包含图片的网络下载,本地缓存,查看大图,从相册选取多张图片等。" items:@[ item10, item11, item12, item13 ]]; [dataSource addObject:section1]; STDTableViewCellItem *item20 = [[STDTableViewCellItem alloc] initWithTitle:@"Label样式" target:self action:@selector(linkActionFired)]; STDTableViewCellItem *item21 = [[STDTableViewCellItem alloc] initWithTitle:@"超链接文本" target:self action:@selector(textActionFired)]; STDTableViewSectionItem *section2 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"包含UILabel的各种对齐方式" items:@[ item20, item21 ]]; [dataSource addObject:section2]; STDTableViewCellItem *item30 = [[STDTableViewCellItem alloc] initWithTitle:@"翻栏提醒" target:self action:@selector(notificationActionFired)]; STDTableViewSectionItem *section3 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"应用内的提醒, 适合即时通讯类的收到消息时提示" items:@[ item30 ]]; [dataSource addObject:section3]; STDTableViewCellItem *item40 = [[STDTableViewCellItem alloc] initWithTitle:@"内嵌网页" target:self action:@selector(webViewActionFired)]; STDTableViewSectionItem *section4 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"目前只提供了导航的功能,稍后会加入与Native交互的功能" items:@[ item40 ]]; [dataSource addObject:section4]; STDTableViewCellItem *item50 = [[STDTableViewCellItem alloc] initWithTitle:@"WebViewScrollView" target:self action:@selector(frameVSBoundsActionFired)]; STDTableViewSectionItem *section5 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"ScrollViewController" items:@[ item50 ]]; [dataSource addObject:section5]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"基本组件"; self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; if (self.st_sideBarController) { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.autoresizingMask = UIViewAutoresizingFlexibleHeight; button.frame = CGRectMake(0, 0, 60, 44); [button setImage:[UIImage imageNamed:@"nav_menu_normal.png"] forState:UIControlStateNormal]; button.contentEdgeInsets = UIEdgeInsetsMake(2.5, 2.5, 2.5, 2.5); [button addTarget:self action:@selector(leftBarButtonItemAction:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; } } - (void)_longPressActionFired:(UIGestureRecognizer *)gesture { NSLog(@"%@", NSStringFromCGPoint([gesture locationInView:self.view])); } - (void)_changeRowActionFired:(id)sender { STDTableViewSectionItem *sectionItem0 = self.dataSource[0]; STDTableViewSectionItem *sectionItem1 = self.dataSource[1]; NSMutableArray *items0 = [sectionItem0.items mutableCopy]; NSMutableArray *items1 = [sectionItem1.items mutableCopy]; NSIndexPath *fromIndexPath; NSIndexPath *targetIndexPath; if (items0.count == 2) { // 从0 到2 id item0 = [items0 lastObject]; [items1 addObject:item0]; [items0 removeLastObject]; sectionItem0.items = items0; sectionItem1.items = items1; fromIndexPath = [NSIndexPath indexPathForRow:1 inSection:0]; targetIndexPath = [NSIndexPath indexPathForRow:0 inSection:1]; } else { id item1 = [items1 firstObject]; [items0 addObject:item1]; [items1 removeObjectAtIndex:0]; sectionItem0.items = items0; sectionItem1.items = items1; fromIndexPath = [NSIndexPath indexPathForRow:0 inSection:1]; targetIndexPath = [NSIndexPath indexPathForRow:1 inSection:0]; } [self.tableView beginUpdates]; [self.tableView moveRowAtIndexPath:fromIndexPath toIndexPath:targetIndexPath]; [self.tableView endUpdates]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)testNavigationActionFired { STDNavigationTestViewController *viewController = [[STDNavigationTestViewController alloc] initWithStyle:UITableViewStyleGrouped]; viewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)imageDownloadActionFired { STDownloadViewController *viewController = STDownloadViewController.new; viewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)imageCardActionFired { STDCardViewController *cardViewController = STDCardViewController.new; cardViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:cardViewController animated:YES]; } - (void)imagePickerActionFired { STImagePickerController *imagePickerController = STImagePickerController.new; imagePickerController.delegate = self; [self presentViewController:imagePickerController animated:YES completion:NULL]; } - (void)imageBlurActionFired { STDImageBlurViewController *imageBlurViewController = [[STDImageBlurViewController alloc] init]; imageBlurViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:imageBlurViewController animated:YES]; } - (void)textActionFired { STDTextViewController *textViewController = STDTextViewController.new; textViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:textViewController animated:YES]; } - (void)linkActionFired { STDLinkViewController *linkViewController = STDLinkViewController.new; linkViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:linkViewController animated:YES]; } - (void)notificationActionFired { NSMutableDictionary *notificationInfo = [NSMutableDictionary dictionaryWithCapacity:2]; [notificationInfo setValue:@"友情提醒" forKey:STNotificationViewTitleTextKey]; [notificationInfo setValue:@"这是一条来自应用内部的提醒" forKey:STNotificationViewDetailTextKey]; STNotificationView *notificationView = [STNotificationWindow notificationViewWithInfo:notificationInfo]; [self.notificationWindow pushNotificationView:notificationView animated:YES]; } - (void)webViewActionFired { STWebViewController *webViewController = [[STWebViewController alloc] initWithURLString:@"http://xstore.duapp.com"]; [self.st_navigationController pushViewController:webViewController animated:YES]; } - (void)frameVSBoundsActionFired { STDScrollViewController *scrollViewController = [[STDScrollViewController alloc] init]; [self.st_navigationController pushViewController:scrollViewController animated:YES]; } - (void)imagePickerController:(STImagePickerController *)picker didFinishPickingImageWithInfo:(NSDictionary *)info { NSArray *imageArray = [info valueForKey:@"data"]; STIndicatorView *indicatorView = [[STIndicatorView alloc] initWithView:self.view]; indicatorView.indicatorType = STIndicatorTypeText; indicatorView.blurEffectStyle = STBlurEffectStyleExtraLight; indicatorView.textLabel.text = @"完成选择照片"; indicatorView.detailLabel.text = [NSString stringWithFormat:@"该次选择 %lld 张照片", (long long)imageArray.count]; [indicatorView showAnimated:NO]; [indicatorView hideAnimated:YES afterDelay:2.5]; [picker dismissViewControllerAnimated:YES completion:nil]; } - (void)imagePickerControllerDidCancel:(STImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:nil]; } - (STNotificationWindow *)notificationWindow { if (!_notificationWindow) { _notificationWindow = [[STNotificationWindow alloc] init]; _notificationWindow.notificationWindowDelegate = self; _notificationWindow.maximumNumberOfWindows = 3; _notificationWindow.displayDuration = 5; } return _notificationWindow; } - (void)allNoticationViewDismissed { self.notificationWindow = nil; } - (void)leftBarButtonItemAction:(id)sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } - (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar { self.st_navigationBarHidden = YES; } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDAboutViewController.h ================================================ // // STDAboutViewController.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDAboutViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDAboutViewController.m ================================================ // // STDAboutViewController.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDAboutViewController.h" #import @interface STDAboutViewController () @property(nonatomic, strong) STLinkLabel *linkLabel; @property(nonatomic, strong) NSString *horizontalString; @property(nonatomic, strong) NSString *verticalString; @end @implementation STDAboutViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.hidesBottomBarWhenPushed = YES; self.verticalString = @"\n大家好,我是@技术哥\ue415\ue415" @",欢迎使用STKit。\n\n\tSTKit目前仍然在建设中,未来还需要大量的测试和验证以及各位亲们的帮助,我也开通了自己的博客,以后会坚持分享我的知" @"识。\n\n我的邮箱:lovesunstar@sina.com\n我的博客:http://suenblog.duapp.com " @"\n\n欢迎大家关注,我会努力贡献的。\n\n再这里先鄙视下我的坑爹队友:@王磊²,说好的一起写呢,迄今为止没有贡献过任何代码,强烈鄙视,强烈谴责。测试捐钱\n\nCopyright @2013-2014"; self.horizontalString = @"大家好,我是@技术哥" @",欢迎使用STKit。\n\tSTKit目前仍然在建设中,未来还需要大量的测试和验证以及各位亲们的帮助,我也开通了自己的博客,以" @"后会坚持分享我的知识。\n我的邮箱:lovesunstar@sina.com\n我的博客:http://" @"suenblog.duapp.com\n欢迎大家关注,我会努力贡献的。\n再这里先鄙视下我的坑爹队友:@王磊,说好的一起写呢,迄今为止没有贡献过任何代码,强烈鄙视,强烈谴责。\nCopyright " @"@2013-2014"; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"关于STKit"; self.st_navigationBar.barTintColor = [UIColor st_colorWithRGB:0x32BBF8]; self.st_navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor st_colorWithRGB:0xF1F2F3]}; if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeRight; } self.linkLabel = [[STLinkLabel alloc] initWithFrame:self.view.bounds]; self.linkLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.linkLabel.backgroundColor = [UIColor clearColor]; self.linkLabel.textCheckingTypes = STTextCheckingTypeCustomLink | NSTextCheckingTypeLink; self.linkLabel.delegate = self; self.linkLabel.text = self.verticalString; [self.view addSubview:self.linkLabel]; } - (void)linkLabel:(STLinkLabel *)linkLabel didSelectLinkObject:(STLinkObject *)linkObject { NSURL *URL = linkObject.URL; if ([[URL scheme] isEqualToString:@"mailto"]) { MFMailComposeViewController *viewController = [[MFMailComposeViewController alloc] init]; viewController.navigationBar.tintColor = [UIColor st_colorWithRGB:0xFF7300]; [viewController setToRecipients:@[ @"lovesunstar@sina.com" ]]; [viewController setCcRecipients:@[ @"97676901@qq.com" ]]; [viewController setBccRecipients:nil]; [viewController setSubject:@"【STKit】意见反馈"]; [viewController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor st_colorWithRGB:0xFF7300]}]; [viewController setMessageBody:[NSString stringWithFormat:@"Dear 技术哥:


当前版本 %@
", [STApplicationContext sharedContext].bundleVersion] isHTML:YES]; viewController.mailComposeDelegate = self; [self presentViewController:viewController animated:YES completion:NULL]; return; } if (URL) { if ([[STApplicationContext sharedContext] canOpenURL:URL]) { [[STApplicationContext sharedContext] openURL:URL]; return; } STWebViewController *webViewController = [[STWebViewController alloc] initWithURL:URL]; [self.st_navigationController pushViewController:webViewController animated:YES]; } else { NSString *value = linkObject.value; NSArray *components = [value componentsSeparatedByString:@"|"]; NSString *message, *title; if (components.count > 0) { message = components[0]; if (components.count > 1) { title = components[1]; } } UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:message message:nil delegate:nil cancelButtonTitle:title otherButtonTitles:nil, nil]; [alertView st_showWithDismissBlock:NULL]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { [controller dismissViewControllerAnimated:YES completion:NULL]; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { self.linkLabel.text = self.horizontalString; } else { self.linkLabel.text = self.verticalString; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDLinkViewController.h ================================================ // // STDLinkViewController.h // STKitDemo // // Created by SunJiangting on 14-12-24. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTableViewController.h" @interface STDLinkViewController : STDTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDLinkViewController.m ================================================ // // STDLinkViewController.m // STKitDemo // // Created by SunJiangting on 14-12-24. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDLinkViewController.h" #import @interface STDLinkViewCell : UITableViewCell + (UIFont *)preferredLinkLabelFont; @property (nonatomic, strong) STLinkLabel *linkLabel; @end @implementation STDLinkViewCell + (UIFont *)preferredLinkLabelFont { static UIFont *font; if (!font) { font = [UIFont systemFontOfSize:17]; } return font; } CGSize const STDLinkViewCellSize = {320, 40}; - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.frame = CGRectMake(0, 0, STDLinkViewCellSize.width, STDLinkViewCellSize.height); self.linkLabel = [[STLinkLabel alloc] initWithFrame:CGRectMake(5, 5, 310, 30)]; self.linkLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.linkLabel.font = [[self class] preferredLinkLabelFont]; self.linkLabel.continueTouchEvent = NO; self.linkLabel.delegate = self; [self addSubview:self.linkLabel]; self.selectionStyle = UITableViewCellSelectionStyleNone; } return self; } - (void) linkLabel:(STLinkLabel *) linkLabel didSelectLinkObject:(STLinkObject *) linkObject { NSURL * URL = linkObject.URL; if ([[URL scheme] isEqualToString:@"mailto"]) { MFMailComposeViewController * viewController = [[MFMailComposeViewController alloc] init]; viewController.navigationBar.tintColor = [UIColor st_colorWithRGB:0xFF7300]; [viewController setToRecipients:@[@"lovesunstar@sina.com"]]; [viewController setCcRecipients:@[@"97676901@qq.com"]]; [viewController setBccRecipients:nil]; [viewController setSubject:@"【STKit】意见反馈"]; [viewController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor st_colorWithRGB:0xFF7300]}]; [viewController setMessageBody:[NSString stringWithFormat:@"Dear 技术哥:


当前版本 %@
", [STApplicationContext sharedContext].bundleVersion] isHTML:YES]; viewController.mailComposeDelegate = self; [self.viewController presentViewController:viewController animated:YES completion:NULL]; return; } if (URL) { if ([[STApplicationContext sharedContext] canOpenURL:URL]) { [[STApplicationContext sharedContext] openURL:URL]; return; } STWebViewController * webViewController = [[STWebViewController alloc] initWithURL:URL]; [self.viewController.st_navigationController pushViewController:webViewController animated:YES]; } else { NSString * value = linkObject.value; NSArray * components = [value componentsSeparatedByString:@"|"]; NSString * message, * title; if (components.count > 0) { message = components[0]; if (components.count > 1) { title = components[1]; } } UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:message message:nil delegate:nil cancelButtonTitle:title otherButtonTitles:nil, nil]; [alertView st_showWithDismissBlock:NULL]; } } - (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error { [controller dismissViewControllerAnimated:YES completion:NULL]; } @end @interface STDLinkViewController () @property (nonatomic, strong) NSMutableArray *dataSource; @end @implementation STDLinkViewController - (instancetype)initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:2]; [dataSource addObject:@"大家好,我是@技术哥,欢迎使用STKit。\n\n\tSTKit目前仍然在建设中,未来还需要大量的测试和验证以及各位亲们的帮助,我也开通了自己的博客,以后会坚持分享我的知识。\n\n我的邮箱:lovesunstar@sina.com\n我的博客:http://suenblog.duapp.com \n\n欢迎大家关注,我会努力贡献的。\n\n再这里先鄙视下我的坑爹队友:@王磊²,说好的一起写呢,迄今为止没有贡献过任何代码,强烈鄙视,强烈谴责。测试捐钱\n\nCopyright @2013-2014"]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"STLinkLabel"; [self.tableView registerClass:[STDLinkViewCell class] forCellReuseIdentifier:@"Identifier"]; self.scrollDirector.refreshControl.enabled = NO; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.dataSource.count * 10; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 1; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *text = self.dataSource[indexPath.row / 10]; STDLinkViewCell *linkViewCell = (STDLinkViewCell *)[tableView dequeueReusableCellWithIdentifier:@"Identifier"]; linkViewCell.linkLabel.text = text; return linkViewCell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *text = self.dataSource[indexPath.row / 10]; CGSize size = [STLinkLabel sizeWithText:text font:[STDLinkViewCell preferredLinkLabelFont] constrainedToSize:CGSizeMake(tableView.width - 10, 9999) paragraphStyle:nil]; return size.height + 10; } /* #pragma mark - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. } */ @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDTextViewController.h ================================================ // // STDTextViewController.h // STKitDemo // // Created by SunJiangting on 14-5-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDTextViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Components/TextLayout/STDTextViewController.m ================================================ // // STDTextViewController.m // STKitDemo // // Created by SunJiangting on 14-5-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDTextViewController.h" @interface STDTextViewController () @property (nonatomic, strong) STLabel *linkLabel; @end @implementation STDTextViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"图文混排"; self.edgesForExtendedLayout = UIRectEdgeNone; self.linkLabel = [[STLabel alloc] initWithFrame:self.view.bounds]; self.linkLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.linkLabel.numberOfLines = 0; self.linkLabel.backgroundColor = self.view.backgroundColor; self.linkLabel.verticalAlignment = STVerticalAlignmentTop; self.linkLabel.markedText = @"大家好\t这里演示的是文字的排版。该段内容里面会包含下划线,删除线等等。字体的颜色和大小也是可以随意调整的。这一期没有加入图片的排版将会在下一期中加入。"; self.linkLabel.contentInsets = UIEdgeInsetsMake(10, 5, 10, 10); [self.view addSubview:self.linkLabel]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDAbstractFactory.h ================================================ // // STDAbstractFactory.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDesignPatterns.h" @protocol STDAbstractProduct; /** * @abstract 抽象工厂模式 * * 抽象工厂中有四个角色,抽象工厂,工厂,抽象产品,产品 */ @interface STDAbstractFactory : NSObject + (id )createProduct; @end @interface STDFactoryA : STDAbstractFactory @end @interface STDFactoryB : STDAbstractFactory @end // ... /* 如果需要扩展,就在这里扩展一个工厂 @interface STDFactoryC : STDAbstractFactory @end */ @interface STDProductA : NSObject @end @interface STDProductB : NSObject @end // ... ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDAbstractFactory.m ================================================ // // STDAbstractFactory.m // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDAbstractFactory.h" @implementation STDAbstractFactory + (void)test { id productA = [STDFactoryA createProduct]; [productA printProductName]; id productB = [STDFactoryB createProduct]; [productB printProductName]; } + (id )createProduct { return nil; } - (void)printDesignPatternName { NSLog(@"抽象工厂模式"); } - (void)printAdvantages { } - (void)printDisadvantages { } @end @implementation STDFactoryA + (id )createProduct { return STDProductA.new; } @end @implementation STDFactoryB + (id )createProduct { return STDProductB.new; } @end @implementation STDProductA - (void)printProductName { NSLog(@"=========This is product a."); } @end @implementation STDProductB - (void)printProductName { NSLog(@"=========This is product b."); } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDBuilder.h ================================================ // // STDBuilder.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDesignPatterns.h" @interface STDProduct : NSObject @property (nonatomic) NSObject *partA, *partB, *partC, *partD; @end /// 建造者模式 @interface STDBuilder : NSObject - (void)buildPartA; - (void)buildPartB; - (void)buildPartC; - (void)buildPartD; - (STDProduct *)product; @end @interface STDBuildDirector : NSObject - (instancetype)initWithBuilder:(STDBuilder *)builder; - (STDProduct *)construct; - (STDProduct *)constructWithBuilder:(STDBuilder *)builder; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDBuilder.m ================================================ // // STDBuilder.m // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDBuilder.h" @implementation STDProduct - (NSString *)description { NSMutableString *description = [NSMutableString string]; if (self.partA) { [description appendFormat:@"\n%@", self.partA]; } if (self.partB) { [description appendFormat:@"\n%@", self.partB]; } if (self.partC) { [description appendFormat:@"\n%@", self.partC]; } if (self.partD) { [description appendFormat:@"\n%@", self.partD]; } return [description copy]; } @end @interface STDBuilder () @property (nonatomic)STDProduct *product; @end @implementation STDBuilder + (void)test { STDBuilder *builder = STDBuilder.new; STDBuildDirector *director = [[STDBuildDirector alloc] initWithBuilder:builder]; STDProduct *product = [director construct]; NSLog(@"%@", product); } - (instancetype)init { self = [super init]; if (self) { self.product = STDProduct.new; } return self; } - (void)buildPartA { self.product.partA = @"I have part a."; } - (void)buildPartB { self.product.partB = @"I have part b."; } - (void)buildPartC { self.product.partC = @"I have part c."; } - (void)buildPartD { self.product.partD = @"I have part d."; } - (STDProduct *)product { return self.product; } @end @interface STDBuildDirector () @property (nonatomic)STDBuilder *builder; @end @implementation STDBuildDirector - (instancetype)initWithBuilder:(STDBuilder *)builder { self = [super init]; if (self) { self.builder = builder; } return self; } - (STDProduct *)construct { return [self constructWithBuilder:self.builder]; } - (STDProduct *)constructWithBuilder:(STDBuilder *)builder { [builder buildPartA]; [builder buildPartB]; [builder buildPartC]; [builder buildPartD]; return self.builder.product; } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDFactoryMethod.h ================================================ // // STDFactoryMethod.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDesignPatterns.h" /** * @abstract 工厂方法模式 */ @interface STDFactoryMethod : NSObject + (id)createProduct; @end @interface STDFactoryMethodProduct : NSObject @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDFactoryMethod.m ================================================ // // STDFactoryMethod.m // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDFactoryMethod.h" @implementation STDFactoryMethod + (void)test { id product = [STDFactoryMethod createProduct]; [product printProductName]; } + (id)createProduct { return STDFactoryMethodProduct.new; } - (void)printDesignPatternName { NSLog(@"工厂方法模式"); } @end @implementation STDFactoryMethodProduct - (void)printProductName { NSLog(@"This is a product"); } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDPrototype.h ================================================ // // STDPrototype.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDesignPatterns.h" @interface STDPrototype : NSObject @property (nonatomic, strong) NSString *propertyA; @property (nonatomic, strong) NSDictionary *propertyB; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDPrototype.m ================================================ // // STDPrototype.m // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDPrototype.h" @implementation STDPrototype + (void)test { STDPrototype *prototype = [[STDPrototype alloc] init]; prototype.propertyA = @"abc"; prototype.propertyB = @{@"key":@"value"}; NSLog(@"Original%@", prototype); STDPrototype *prototype1 = [prototype copy]; STDPrototype *prototype2 = [prototype mutableCopy]; NSLog(@"Copy %@", prototype1); prototype1.propertyA = @"Modified"; NSLog(@"Modified CopiedObject Origin%@ Copy%@ MutableCopy %@", prototype, prototype1, prototype2); prototype2.propertyA = @"MutableProperty"; NSLog(@"Modified MutableCopiedObject Origin%@ Copy%@ MutableCopy %@", prototype, prototype1, prototype2); } - (instancetype)copyWithZone:(NSZone *)zone { STDPrototype *prototype = [[[self class] allocWithZone:zone] init]; prototype.propertyA = [self.propertyA copy]; prototype.propertyB = [self.propertyB copy]; return prototype; } - (instancetype)mutableCopyWithZone:(NSZone *)zone { STDPrototype *prototype = [[[self class] allocWithZone:zone] init]; prototype.propertyA = [self.propertyA mutableCopy]; prototype.propertyB = [self.propertyB mutableCopy]; return prototype; } - (NSString *)description { NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:2]; [dictionary setValue:self.propertyA forKey:@"propertyA"]; [dictionary setValue:self.propertyB forKey:@"propertyB"]; return [dictionary description]; } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDSingleton.h ================================================ // // STDSingleton.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDesignPatterns.h" @interface STDSingleton : NSObject + (instancetype)sharedInstance; @property (nonatomic, copy)NSString *globalName; - (void)printMemoryAddress; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Creational/STDSingleton.m ================================================ // // STDSingleton.m // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDSingleton.h" @implementation STDSingleton + (void)test { [STDSingleton sharedInstance].globalName = @"Suen技术哥"; [[STDSingleton sharedInstance] printMemoryAddress]; [[STDSingleton sharedInstance] printMemoryAddress]; } static STDSingleton *_sharedInstance; + (instancetype)sharedInstance { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[self alloc] init]; }); return _sharedInstance; } - (void)printMemoryAddress { NSLog(@"%p", self); } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/STDesignPatterns.h ================================================ // // STDesignPatterns.h // STKitDemo // // Created by SunJiangting on 15-2-3. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @protocol STDesignPatternsDelegate + (void)test; @optional - (void)printDesignPatternName; - (void)printAdvantages; - (void)printDisadvantages; @end /// 工厂部分 /// 抽象产品,提供一个制造的接口 @protocol STDAbstractProduct - (void)printProductName; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDAdapter.h ================================================ // // STDAdapter.h // STKitDemo // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDesignPatterns.h" @protocol STDAdapter - (void)AFRequestWithURLString:(NSString *)URLString; @end @interface STDASINetwork : NSObject - (void)ASIRequestWithURLString:(NSString *)URLString; @end @interface STDAFNetwork : NSObject - (void)AFRequestWithURLString:(NSString *)URLString; @end /// 适配器模式 @interface STDAdapter : STDASINetwork - (instancetype)initWithAFNetwork:(STDAFNetwork *)AFNetwork; - (void)AFRequestWithURLString:(NSString *)URLString; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDAdapter.m ================================================ // // STDAdapter.m // STKitDemo // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDAdapter.h" @implementation STDASINetwork - (void)ASIRequestWithURLString:(NSString *)URLString { NSLog(@"ASISendRequestWithURLString %@", URLString); } @end @implementation STDAFNetwork - (void)AFRequestWithURLString:(NSString *)URLString { NSLog(@"AFSendRequestWithURLString %@", URLString); } @end @interface STDAdapter () @property (nonatomic, strong) STDAFNetwork *AFNetwork; @end @implementation STDAdapter + (void)test { STDAFNetwork *AFNetwork = [[STDAFNetwork alloc] init]; STDAdapter *adapter = [[STDAdapter alloc] initWithAFNetwork:AFNetwork]; [adapter AFRequestWithURLString:@"http://suenblog.duapp.com"]; [adapter ASIRequestWithURLString:@"http://suenblog.duapp.com"]; } - (instancetype)initWithAFNetwork:(STDAFNetwork *)AFNetwork { self = [super init]; if (self) { self.AFNetwork = AFNetwork; } return self; } - (void)AFRequestWithURLString:(NSString *)URLString { [self.AFNetwork AFRequestWithURLString:URLString]; } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDBridge.h ================================================ // // STDBridge.h // STKitDemo // // Created by SunJiangting on 15-2-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDesignPatterns.h" @interface STDBridge : NSObject @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDBridge.m ================================================ // // STDBridge.m // STKitDemo // // Created by SunJiangting on 15-2-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDBridge.h" @implementation STDBridge + (void)test { } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDFacade.h ================================================ // // STDFacade.h // STKitDemo // // Created by SunJiangting on 15-2-5. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDesignPatterns.h" @interface STDFObjectA : NSObject - (void)methodA; @end @interface STDFObjectB : NSObject - (void)methodB; @end @interface STDFObjectC : NSObject - (void)methodC; @end @interface STDFObjectD : NSObject - (void)methodD; @end @interface STDFacade : NSObject - (void)unifiedMethodA; - (void)unifiedMethodB; - (void)unifiedMethodC; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDFacade.m ================================================ // // STDFacade.m // STKitDemo // // Created by SunJiangting on 15-2-5. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDFacade.h" @implementation STDFObjectA - (void)methodA { NSLog(@"%@Method", [self class]); } @end @implementation STDFObjectB - (void)methodB { NSLog(@"%@Method", [self class]); } @end @implementation STDFObjectC - (void)methodC { NSLog(@"%@Method", [self class]); } @end @implementation STDFObjectD - (void)methodD { NSLog(@"%@Method", [self class]); } @end @interface STDFacade () @property (nonatomic, strong) STDFObjectA *objectA; @property (nonatomic, strong) STDFObjectB *objectB; @property (nonatomic, strong) STDFObjectC *objectC; @property (nonatomic, strong) STDFObjectD *objectD; @end @implementation STDFacade + (void)test { STDFacade *facade = [[STDFacade alloc] init]; [facade unifiedMethodA]; [facade unifiedMethodB]; [facade unifiedMethodC]; } - (instancetype)init { self = [super init]; if (self) { self.objectA = [STDFObjectA new]; self.objectB = [STDFObjectB new]; self.objectC = [STDFObjectC new]; self.objectD = [STDFObjectD new]; } return self; } - (void)unifiedMethodA { [self.objectA methodA]; [self.objectB methodB]; [self.objectC methodC]; } - (void)unifiedMethodB { [self.objectD methodD]; [self.objectB methodB]; [self.objectC methodC]; } - (void)unifiedMethodC { [self.objectA methodA]; [self.objectB methodB]; [self.objectD methodD]; } @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDProxy.h ================================================ // // STDProxy.h // STKitDemo // // Created by SunJiangting on 15-2-5. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDesignPatterns.h" @protocol STDPObject - (void)methodA; - (void)methodB; @end @interface STDPObject : NSObject @end @interface STDProxy : NSObject - (instancetype)initWithObject:(id)object; @end ================================================ FILE: STKitDemo/Classes/Modules/DesignPatterns/Structural/STDProxy.m ================================================ // // STDProxy.m // STKitDemo // // Created by SunJiangting on 15-2-5. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDProxy.h" @implementation STDPObject - (void)methodA { NSLog(@"%@ methodA", [self class]); } - (void)methodB { NSLog(@"%@ methodB", [self class]); } @end @interface STDProxy () @property (nonatomic, strong) NSObject *object; @property (nonatomic, getter=hasPermission) BOOL hasPermission; @end @implementation STDProxy + (void)test { STDPObject *object = [[STDPObject alloc] init]; STDProxy *proxy = [[STDProxy alloc] initWithObject:object]; proxy.hasPermission = YES; [proxy methodA]; [proxy methodB]; proxy.hasPermission = NO; [proxy methodA]; [proxy methodB]; } - (instancetype)initWithObject:(id)object { self = [super init]; if (self) { self.object = object; } return self; } - (void)methodA { if (self.hasPermission) { [self.object methodA]; } else { NSLog(@"===您没有权利调用Method方法"); } } - (void)methodB { [self.object methodB]; } @end ================================================ FILE: STKitDemo/Classes/Modules/STDSideBar/STDMapViewController.h ================================================ // // STDMapViewController.h // STKitDemo // // Created by SunJiangting on 14-3-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDMapViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/STDSideBar/STDMapViewController.m ================================================ // // STDMapViewController.m // STKitDemo // // Created by SunJiangting on 14-3-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDMapViewController.h" @interface STDMapViewController () @end @implementation STDMapViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.navigationItem.title = @"测试测试"; self.st_navigationController.st_sideInteractionArea = STSideInteractiveAreaNavigationBar; self.edgesForExtendedLayout = (UIRectEdgeLeft | UIRectEdgeRight); if (self.st_sideBarController) { UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; button.autoresizingMask = UIViewAutoresizingFlexibleHeight; button.frame = CGRectMake(0, 0, 60, 44); [button setImage:[UIImage imageNamed:@"nav_menu_normal.png"] forState:UIControlStateNormal]; button.contentEdgeInsets = UIEdgeInsetsMake(2.5, 2.5, 2.5, 2.5); [button addTarget:self action:@selector(leftBarButtonItemAction:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; } self.view.backgroundColor = [UIColor whiteColor]; [[STLocationManager sharedManager] requestAlwaysAuthorization]; } - (void) leftBarButtonItemAction:(id) sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/STDSideBar/STDMapViewController.xib ================================================ ================================================ FILE: STKitDemo/Classes/Modules/STDStartViewController.h ================================================ // // STDStartViewController.h // STKitDemo // // Created by SunJiangting on 14-2-20. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import "STDViewController.h" @interface STDStartViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/STDStartViewController.m ================================================ // // STDStartViewController.m // STKitDemo // // Created by SunJiangting on 14-2-20. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDStartViewController.h" #import "STDAppDelegate.h" @interface STDStartViewController () @end @implementation STDStartViewController - (void) dealloc { } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColor st_colorWithRGB:0x35495D]; UIImage *image = [UIImage imageNamed:@"aero_button"]; UIButton *tabBarButton = [UIButton buttonWithType:UIButtonTypeCustom]; tabBarButton.translatesAutoresizingMaskIntoConstraints = NO; [tabBarButton setBackgroundImage:image forState:UIControlStateNormal]; [tabBarButton setTitle:@"STTabBarController" forState:UIControlStateNormal]; [tabBarButton addTarget:self action:@selector(enterTabBarControllerAction:) forControlEvents:UIControlEventTouchUpInside]; tabBarButton.titleLabel.adjustsFontSizeToFitWidth = YES; [self.view addSubview:tabBarButton]; UIButton * sideBarButton = [UIButton buttonWithType:UIButtonTypeCustom]; sideBarButton.translatesAutoresizingMaskIntoConstraints = NO; [sideBarButton setBackgroundImage:image forState:UIControlStateNormal]; [sideBarButton setTitle:@"STSideBarController" forState:UIControlStateNormal]; [sideBarButton addTarget:self action:@selector(enterSideBarControllerAction:) forControlEvents:UIControlEventTouchUpInside]; sideBarButton.titleLabel.adjustsFontSizeToFitWidth = YES; [self.view addSubview:sideBarButton]; NSDictionary *views = @{@"tabBarButton":tabBarButton, @"sideBarButton":sideBarButton}; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=10)-[tabBarButton(==40)]-10-|" options:0 metrics:nil views:views]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-15-[tabBarButton(==140)]-(>=10)-[sideBarButton(tabBarButton)]-15-|" options:0 metrics:nil views:views]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:tabBarButton attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:sideBarButton attribute:NSLayoutAttributeTop multiplier:1. constant:0.]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:tabBarButton attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:sideBarButton attribute:NSLayoutAttributeHeight multiplier:1. constant:0.]]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; UIApplication *application = [UIApplication sharedApplication]; if ([application respondsToSelector:@selector(setStatusBarStyle:)]) { application.statusBarStyle = UIStatusBarStyleLightContent; } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; UIApplication *application = [UIApplication sharedApplication]; if ([application respondsToSelector:@selector(setStatusBarStyle:)]) { application.statusBarStyle = UIStatusBarStyleDefault; } } - (void)enterTabBarControllerAction:(id) sender { STDAppDelegate *appDelegate = (STDAppDelegate *)[UIApplication sharedApplication].delegate; [appDelegate replaceRootViewController:[appDelegate tabBarController] animationOptions:UIViewAnimationOptionTransitionFlipFromLeft]; } - (void)enterSideBarControllerAction:(id) sender { STDAppDelegate *appDelegate = (STDAppDelegate *)[UIApplication sharedApplication].delegate; [appDelegate replaceRootViewController:[appDelegate sideBarController] animationOptions:UIViewAnimationOptionTransitionFlipFromLeft]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } - (BOOL)shouldAutorotate { return NO; } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STACodeViewController.h ================================================ // // STACodeViewController.h // STBasic // // Created by SunJiangting on 13-11-4. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STDViewController.h" #import "STASortDefines.h" @interface STACodeViewController : STDViewController @property (nonatomic, assign) STAlgorithmType algorithmType; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STACodeViewController.m ================================================ // // STACodeViewController.m // STBasic // // Created by SunJiangting on 13-11-4. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STACodeViewController.h" @interface STACodeViewController () @property (nonatomic, strong) UITextView *textView; @end @implementation STACodeViewController - (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.hidesBottomBarWhenPushed = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"源码"; self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 80, 320, 400)]; self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth; self.textView.font = [UIFont systemFontOfSize:14]; self.textView.editable = NO; [self.view addSubview:self.textView]; NSString *insert = @"void insert(int[] a) {\n\tfor (int i = 1; i < a.length; i ++) {\n\t\tint ai = a[i], aj;\n\t\tint j = i;\n\t\twhile (j > 0 && (aj = a[j - 1]) > ai) {\n\t\t\ta[j] = aj;\n\t\t\tj --;\n\t\t}\n\t\ta[j] = ai;\n\t}\n}\n"; NSString *bubble = @"void bubble(int[] a) {\n\tBOOL exchanged = YES;\n\tfor (int i = 0; i < a.length - 1 && exchanged; i ++) {\n\t\texchanged = NO;\n\t\tfor (int j = 0; j < (a.length - 1 - i); j ++) {\n\t\t\tint aj = a[j];\n\t\t\tint aj1 = a[j + 1];\n\t\t\tif (aj > aj1) {\n\t\t\t\texchanged = YES;\n\t\t\t\ta[j + 1] = aj;\n\t\t\t\ta[j] = aj1;\n\t\t\t}\n\t\t}\n\t}\n}\n"; NSString *select = @"void select(int[] a) {\n\tfor(int i = 0; i < a.length;i ++) {\n\t\tfor(int j = i; j < a.length; j ++) {\n\t\tint ai = a[i];\n\t\tint aj = a[j];\n\t\tif(a[i] > a[j]) {\n\t\t\ta[i] = aj\n\t\t\ta[j] = ai;\n\t\t}\n\t}\n}"; NSString *quick = @"void quick(int[] a, int left, int right){\tif (left < right) {\n\t\tint key = a[left];\n\t\tint low = left;\n\t\tint high = right;\n\t\twhile (low < high) {\n\t\t\twhile (low < high && a[high] >= key) {\n\t\t\t\thigh --;\n\t\t\t}\n\t\t\ta[low] = a[high];\n\t\t\twhile (low < high && a[low] <= key) {\n\t\t\t\tlow ++;\n\t\t\t}\n\t\t\ta[high] = a[low];\n\t\t}\n\t\ta[low] = key;\n\t\tquick(a, left, low - 1);\n\t\tquick(a, low + 1, right);\n\t}\n}\n"; NSString *hanoi = @"void hanoi(int i , char A , char B , char C) {\n\tif(i == 1) {\n\t\tmove(i , A , C);\n\t} else {\t\n\t\thanoi(i - 1 , A , C , B);\n\t\tmove(i , A , C);\n\t\thanoi(i - 1 , B , A , C);\n\t}\n}\n\nvoid move(int i , char x , char y) {\n\tprintf(\"Move disk i from x to y\");\n}"; switch (self.algorithmType) { case STAlgorithmTypeInsertSort: self.textView.text = insert; break; case STAlgorithmTypeBubbleSort: self.textView.text = bubble; break; case STAlgorithmTypeSelectSort: self.textView.text = select; break; case STAlgorithmTypeQuickSort: self.textView.text = quick; break; case STAlgorithmTypeHanoi: self.textView.text = hanoi; break; default: break; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiOperation.h ================================================ // // STAHanoiOperation.h // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" @class STAHanoiView; @interface STAHanoiOperation : NSOperation @property (nonatomic, assign) NSInteger index; @property (nonatomic, assign) NSInteger toIndex; @property (nonatomic, weak) STAHanoiView *hanoiView; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiOperation.m ================================================ // // STAHanoiOperation.m // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STAHanoiOperation.h" #import "STAHanoiView.h" @interface STAHanoiOperation () @property (nonatomic, assign) NSTimeInterval duration; @property (atomic, assign) BOOL complete; @end @implementation STAHanoiOperation - (instancetype) init { self = [super init]; if (self) { self.duration = [[[NSUserDefaults standardUserDefaults] valueForKey:@"STMoveAnimationDuration"] doubleValue]; } return self; } - (void) main { void (^completion)(BOOL finished) = ^(BOOL finished){ self.complete = YES; }; dispatch_async(dispatch_get_main_queue(), ^{ [self.hanoiView moveDiskAtIndex:_index toIndex:_toIndex duration:_duration completion:completion]; }); while (!self.complete) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiView.h ================================================ // // STAHanoiView.h // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" @interface STAHanoiView : UIView @property (nonatomic, assign) NSInteger numberOfHanois; - (void) reloadHanoiView; - (void) moveDiskAtIndex:(NSInteger) index toIndex:(NSInteger) toIndex duration:(NSTimeInterval) duration completion:(void(^)(BOOL finished)) completion; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiView.m ================================================ // // STAHanoiView.m // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STAHanoiView.h" @interface STAHanoiView () @property (nonatomic, strong) UIView *columnView1; @property (nonatomic, strong) UIView *columnView2; @property (nonatomic, strong) UIView *columnView3; @property (nonatomic, assign) CGFloat baseWidth; @property (nonatomic, assign) CGFloat baseHeight; @property (nonatomic, strong) NSMutableArray *hanoiViewArray; @property (nonatomic, strong) NSMutableArray *columnHanoi1; @property (nonatomic, strong) NSMutableArray *columnHanoi2; @property (nonatomic, strong) NSMutableArray *columnHanoi3; @property (nonatomic, assign) CGFloat hanoiHeight; @property (nonatomic, assign) CGFloat verticalMargin; @end const NSInteger kSTDiskTagOffset = 100; @implementation STAHanoiView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.baseWidth = CGRectGetWidth(frame) / 3; self.baseHeight = CGRectGetHeight(frame) * 2 / 3; self.columnView1 = [[UIView alloc] initWithFrame:CGRectMake( self.baseWidth * 0.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight)]; self.columnView1.backgroundColor = [UIColor blackColor]; [self addSubview:self.columnView1]; self.columnView2 = [[UIView alloc] initWithFrame:CGRectMake( self.baseWidth * 1.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight)]; self.columnView2.backgroundColor = [UIColor blackColor]; [self addSubview:self.columnView2]; self.columnView3 = [[UIView alloc] initWithFrame:CGRectMake( self.baseWidth * 2.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight)]; self.columnView3.backgroundColor = [UIColor blackColor]; [self addSubview:self.columnView3]; self.hanoiViewArray = [NSMutableArray arrayWithCapacity:3]; self.columnHanoi1 = [NSMutableArray arrayWithCapacity:3]; self.columnHanoi2 = [NSMutableArray arrayWithCapacity:3]; self.columnHanoi3 = [NSMutableArray arrayWithCapacity:3]; } return self; } - (void) layoutSubviews { [super layoutSubviews]; CGRect frame = self.frame; self.baseWidth = CGRectGetWidth(frame) / 3; self.baseHeight = CGRectGetHeight(frame) * 2 / 3; self.columnView1.frame = CGRectMake(self.baseWidth * 0.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight); self.columnView2.frame = CGRectMake(self.baseWidth * 1.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight); self.columnView3.frame = CGRectMake(self.baseWidth * 2.5 - 3, CGRectGetHeight(frame) - self.baseHeight, 6, self.baseHeight); CGFloat height = MIN(self.baseHeight / _numberOfHanois, 15); self.hanoiHeight = height; CGFloat increment = MIN(30, (self.baseWidth - 20) / _numberOfHanois); [self.hanoiViewArray enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { CGRect frame = subview.frame; frame.size.width = self.baseWidth - idx * increment; subview.frame = frame; }]; [self.columnHanoi1 enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { CGPoint center = subview.center; center.x = self.baseWidth * (0 + 0.5); CGFloat centerY = CGRectGetHeight(self.bounds) - idx * self.hanoiHeight - (self.hanoiHeight + 5) / 2 + 5; center.y = centerY; subview.center = center; }]; [self.columnHanoi2 enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { CGPoint center = subview.center; center.x = self.baseWidth * (1 + 0.5); CGFloat centerY = CGRectGetHeight(self.bounds) - idx * self.hanoiHeight - (self.hanoiHeight + 5) / 2 + 5; center.y = centerY; subview.center = center; }]; [self.columnHanoi3 enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { CGPoint center = subview.center; center.x = self.baseWidth * (2 + 0.5); CGFloat centerY = CGRectGetHeight(self.bounds) - idx * self.hanoiHeight - (self.hanoiHeight + 5) / 2 + 5; center.y = centerY; subview.center = center; }]; } - (void)reloadHanoiView { [self.hanoiViewArray enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { [subview removeFromSuperview]; }]; [self.hanoiViewArray removeAllObjects]; [self.columnHanoi1 removeAllObjects]; [self.columnHanoi2 removeAllObjects]; [self.columnHanoi3 removeAllObjects]; CGFloat height = MIN(self.baseHeight / _numberOfHanois, 15); self.hanoiHeight = height; CGFloat increment = MIN(30, (self.baseWidth - 20) / _numberOfHanois); for (int i = 0; i < _numberOfHanois; i ++) { CGFloat width = self.baseWidth - i * increment; CGFloat left = (self.baseWidth - width) / 2; CGFloat top = CGRectGetHeight(self.bounds) - (i + 1) * height + 5; UIView * hanoi = [[UIView alloc] initWithFrame:CGRectMake(left, top, width, height - 5)]; hanoi.backgroundColor = [UIColor orangeColor]; [self addSubview:hanoi]; [self.hanoiViewArray addObject:hanoi]; [self.columnHanoi1 addObject:hanoi]; } } - (void)moveDiskAtIndex:(NSInteger) index toIndex:(NSInteger) toIndex duration:(NSTimeInterval) duration completion:(void(^)(BOOL finished)) completion { NSMutableArray * array1, * array2 = nil; switch (index) { case 0: array1 = self.columnHanoi1; break; case 1: array1 = self.columnHanoi2; break; case 2: array1 = self.columnHanoi3; break; default: break; } switch (toIndex) { case 0: array2 = self.columnHanoi1; break; case 1: array2 = self.columnHanoi2; break; case 2: array2 = self.columnHanoi3; break; default: break; } UIView *view = [array1 lastObject]; [array1 removeObject:view]; CGPoint center = [self centerForHanoiAtColumn:toIndex]; if (view) { [array2 addObject:view]; } [UIView animateWithDuration:duration animations:^{ view.center = center; } completion:^(BOOL finished) { view.center = center; completion(finished); }]; } - (void)setNumberOfHanois:(NSInteger)numberOfHanois { _numberOfHanois = numberOfHanois; [self reloadHanoiView]; } - (CGPoint)centerForHanoiAtColumn:(NSInteger) column { NSArray * array = nil; switch (column) { case 0: array = self.columnHanoi1; break; case 1: array = self.columnHanoi2; break; case 2: array = self.columnHanoi3; break; default: break; } NSInteger count = array.count; CGFloat centerX = self.baseWidth * (column + 0.5); CGFloat centerY = CGRectGetHeight(self.bounds) - count * self.hanoiHeight - (self.hanoiHeight + 5) / 2 + 5; return CGPointMake(centerX, centerY); } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiViewController.h ================================================ // // STAHanoiViewController.h // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" #import "STDViewController.h" @interface STAHanoiViewController : STDViewController @property (nonatomic, assign) NSInteger numberOfHanois; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STAHanoiViewController.m ================================================ // // STHanoiViewController.m // STBasic // // Created by SunJiangting on 13-11-3. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STAHanoiViewController.h" #import "STAHanoiView.h" #import "STAHanoiOperation.h" #import "STACodeViewController.h" @interface STAHanoiViewController () @property (nonatomic, strong) STAHanoiView *hanoiView; @property (nonatomic, strong) NSOperationQueue *animationQueue; @end @implementation STAHanoiViewController - (instancetype) initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.animationQueue = [[NSOperationQueue alloc] init]; self.animationQueue.maxConcurrentOperationCount = 1; self.numberOfHanois = 4; self.hidesBottomBarWhenPushed = YES; } return self; } - (instancetype) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.animationQueue = [[NSOperationQueue alloc] init]; self.animationQueue.maxConcurrentOperationCount = 1; self.numberOfHanois = 4; self.hidesBottomBarWhenPushed = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"汉诺塔"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"源码" target:self action:@selector(viewSourceCode:)]; if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) { self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeRight; } self.hanoiView = STAHanoiView.new; self.hanoiView.translatesAutoresizingMaskIntoConstraints = NO; self.hanoiView.numberOfHanois = self.numberOfHanois; [self.view addSubview:self.hanoiView]; [self.view removeConstraints:self.view.constraints]; NSDictionary *dict = @{@"hanoiView" : self.hanoiView}; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[hanoiView(>=200)]-|" options:0 metrics:nil views:dict]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(20)-[hanoiView(>=100)]-(30)-|" options:0 metrics:nil views:dict]]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self.hanoiView reloadHanoiView]; [self moveHanoiWithNumber:self.numberOfHanois - 1 position0:0 position1:1 position2:2]; } - (void) viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [self.animationQueue cancelAllOperations]; } - (void) moveHanoiWithNumber:(NSInteger)number position0:(NSInteger)position0 position1:(NSInteger)position1 position2:(NSInteger)position2 { if (number == 0) { STAHanoiOperation *operation1 = [[STAHanoiOperation alloc] init]; operation1.index = position0; operation1.toIndex = position2; operation1.hanoiView = self.hanoiView; [self.animationQueue addOperation:operation1]; } else { [self moveHanoiWithNumber:number - 1 position0:position0 position1:position2 position2:position1]; STAHanoiOperation *operation2 = [[STAHanoiOperation alloc] init]; operation2.index = position0; operation2.toIndex = position2; operation2.hanoiView = self.hanoiView; [self.animationQueue addOperation:operation2]; [self moveHanoiWithNumber:number - 1 position0:position1 position1:position0 position2:position2]; } } - (void) viewSourceCode:(id) sender { STACodeViewController *viewController = [[STACodeViewController alloc] initWithNibName:nil bundle:nil]; viewController.algorithmType = STAlgorithmTypeHanoi; [self.st_navigationController pushViewController:viewController animated:YES]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STARootViewController.h ================================================ // // STARootViewController.h // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" #import "STDTextTableViewController.h" @interface STARootViewController : STDTextTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STARootViewController.m ================================================ // // STARootViewController.m // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STARootViewController.h" #import "STASortViewController.h" #import "STAHanoiViewController.h" @interface STARootViewController () @property (nonatomic, strong) NSArray * dataSource; @property (nonatomic, strong) NSArray * sortArray; @property (nonatomic, strong) UILabel * numberOfHanoiDiskLabel; @property (nonatomic, assign) NSInteger numberOfDisks; @end @implementation STARootViewController @dynamic dataSource; - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { self.hidesBottomBarWhenPushed = YES; NSArray * array = @[@(20),@(6),@(2),@(8),@(9),@(12), @(2), @(4), @(3), @(4), @(7), @(11)]; self.sortArray = array; NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:2]; STDTableViewCellItem *item00 = [[STDTableViewCellItem alloc] initWithTitle:@"冒泡排序" target:self action:@selector(_bubbleSortActionFired)]; STDTableViewCellItem *item01 = [[STDTableViewCellItem alloc] initWithTitle:@"选择排序" target:self action:@selector(_selectSortActionFired)]; STDTableViewCellItem *item02 = [[STDTableViewCellItem alloc] initWithTitle:@"插入排序" target:self action:@selector(_insertSortActionFired)]; STDTableViewCellItem *item03 = [[STDTableViewCellItem alloc] initWithTitle:@"快速排序" target:self action:@selector(_quickSortActionFired)]; NSString * section0Title = [NSString stringWithFormat:@"几种常用的排序算法, 排序数据源\n%@", [self.sortArray componentsJoinedByString:@","]]; STDTableViewSectionItem *section0 = [[STDTableViewSectionItem alloc] initWithSectionTitle:section0Title items:@[item00, item01, item02, item03]]; [dataSource addObject:section0]; STDTableViewCellItem *item10 = [[STDTableViewCellItem alloc] initWithTitle:@"汉诺塔算法" target:self action:@selector(_hanoiActionFired)]; STDTableViewSectionItem *section1 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"经典的几种递归算法\n" items:@[item10]]; [dataSource addObject:section1]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.clearsSelectionOnViewWillAppear = YES; self.navigationItem.title = @"算法分析"; UIView *tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 90)]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(20, 10, 80, 30)]; label.textAlignment = NSTextAlignmentLeft; label.text = @"速度"; label.textColor = [UIColor blackColor]; label.backgroundColor = [UIColor clearColor]; [tableHeaderView addSubview:label]; CGFloat duration = [[[NSUserDefaults standardUserDefaults] valueForKey:@"STMoveAnimationDuration"] floatValue]; if (!duration) { duration = 0.5; [[NSUserDefaults standardUserDefaults] setValue:@(duration) forKey:@"STMoveAnimationDuration"]; [[NSUserDefaults standardUserDefaults] synchronize]; } if (duration > 1) { duration = duration / 10; } UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(100, 10, 200, 30)]; [tableHeaderView addSubview:slider]; slider.minimumValue = 1; slider.maximumValue = 10; slider.value = 1 / duration; slider.continuous = NO; [slider addTarget:self action:@selector(speedChanged:) forControlEvents:UIControlEventValueChanged]; UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 80, 30)]; label2.textAlignment = NSTextAlignmentLeft; label2.text = @"汉诺塔数"; label2.backgroundColor = [UIColor clearColor]; label2.textColor = [UIColor blackColor]; [tableHeaderView addSubview:label2]; id disks = [[NSUserDefaults standardUserDefaults] valueForKey:@"STNumberOfHanoiDisks"]; if (!disks) { disks = @(4); } self.numberOfHanoiDiskLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 50, 50, 30)]; self.numberOfHanoiDiskLabel.textAlignment = NSTextAlignmentLeft; [self updateNumberOfDisks:[disks intValue]]; self.numberOfHanoiDiskLabel.textColor = [UIColor blackColor]; self.numberOfHanoiDiskLabel.backgroundColor = [UIColor clearColor]; [tableHeaderView addSubview:self.numberOfHanoiDiskLabel]; UIStepper * stepper = [[UIStepper alloc] initWithFrame:CGRectMake(150, 50, 200, 30)]; stepper.minimumValue = 3; stepper.maximumValue = 10; stepper.value = [disks intValue]; [stepper addTarget:self action:@selector(numberOfDiskChanged:) forControlEvents:UIControlEventValueChanged]; [tableHeaderView addSubview:stepper]; self.tableView.tableHeaderView = tableHeaderView; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)speedChanged:(UISlider *)slider { NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults]; CGFloat value = MAX(MIN(slider.value, 10), 1); CGFloat duration = 1 / value; [userDefault setValue:@(duration) forKey:@"STMoveAnimationDuration"]; [userDefault synchronize]; } - (void)updateNumberOfDisks:(NSInteger)numberOfDisks { self.numberOfDisks = numberOfDisks; self.numberOfHanoiDiskLabel.text = [NSString stringWithFormat:@"%ld", (long)numberOfDisks]; [[NSUserDefaults standardUserDefaults] setValue:@(numberOfDisks) forKey:@"STNumberOfHanoiDisks"]; [[NSUserDefaults standardUserDefaults] synchronize]; } - (void)numberOfDiskChanged:(UIStepper *)sender { [self updateNumberOfDisks:sender.value]; } - (void)_bubbleSortActionFired { STASortViewController * viewController = [[STASortViewController alloc] init]; viewController.sortArray = self.sortArray; viewController.arraySortType = STArraySortTypeBubbleSort; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_selectSortActionFired { STASortViewController * viewController = [[STASortViewController alloc] init]; viewController.sortArray = self.sortArray; viewController.arraySortType = STArraySortTypeSelectSort; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_insertSortActionFired { STASortViewController * viewController = [[STASortViewController alloc] init]; viewController.sortArray = self.sortArray; viewController.arraySortType = STArraySortTypeInsertSort; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_quickSortActionFired { STASortViewController * viewController = [[STASortViewController alloc] init]; viewController.sortArray = self.sortArray; viewController.arraySortType = STArraySortTypeQuickSort; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)_hanoiActionFired { STAHanoiViewController * viewController = [[STAHanoiViewController alloc] init]; viewController.numberOfHanois = self.numberOfDisks; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)leftBarButtonItemAction:(id) sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortDefines.h ================================================ // // STASortDefines.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #ifndef STKitDemo_STASortDefines_h #define STKitDemo_STASortDefines_h typedef enum STAlgorithmType { STAlgorithmTypeBubbleSort = 1, STAlgorithmTypeSelectSort = 2, STAlgorithmTypeInsertSort = 3, STAlgorithmTypeQuickSort = 5, STAlgorithmTypeHanoi = 11, } STAlgorithmType; #endif ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortOperation.h ================================================ // // STSortOperation.h // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" typedef enum STSortOperationType { STSortOperationTypeMoveBaseline1 = 1, STSortOperationTypeMoveBaseline2 = 2, STSortOperationTypeMoveElement = 3, STSortOperationTypeCacheUpElement = 4, STSortOperationTypeCacheDownElement = 5, STSortOperationTypeExchangeElement = 6, } STSortOperationType; @class STASortView; @interface STASortOperation : NSOperation @property (nonatomic, assign) NSTimeInterval duration; @property (nonatomic, assign) NSInteger index1; @property (nonatomic, assign) NSInteger index2; @property (nonatomic, weak) STASortView *sortView; @property (nonatomic, assign) STSortOperationType operationType; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortOperation.m ================================================ // // STASortOperation.m // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STASortOperation.h" #import "STASortView.h" @interface STASortOperation() @property (atomic, assign) BOOL complete; @end @implementation STASortOperation - (instancetype) init { self = [super init]; if (self) { id duration = [[NSUserDefaults standardUserDefaults] valueForKey:@"STMoveAnimationDuration"]; self.duration = [duration doubleValue]; } return self; } - (void) main { void (^completion)(BOOL finished) = ^(BOOL finished) { self.complete = YES; }; dispatch_async(dispatch_get_main_queue(), ^{ switch (_operationType) { case STSortOperationTypeMoveBaseline1: [self.sortView moveBaseline1ToIndex:_index1 duration:self.duration completion:completion]; break; case STSortOperationTypeMoveBaseline2: [self.sortView moveBaseline2ToIndex:_index2 duration:self.duration completion:completion]; break; case STSortOperationTypeCacheUpElement: [self.sortView moveElementToCacheAtIndex:_index1 duration:self.duration completion:completion]; break; case STSortOperationTypeCacheDownElement: [self.sortView removeElementFromCacheWithDuration:self.duration completion:completion]; break; case STSortOperationTypeMoveElement: [self.sortView moveElementAtIndex:_index1 toIndex:_index2 duration:self.duration completion:completion]; break; case STSortOperationTypeExchangeElement: [self.sortView exchangeElementAtIndex:_index1 withElementAtIndex:_index2 duration:self.duration completion:completion]; break; default: break; } }); while (!_complete) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]]; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortView.h ================================================ // // STASortView.h // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" @interface STASortView : UIView /// default 5 @property (nonatomic, assign) NSInteger factor; - (void)reloadSortDataSource:(NSArray *)dataSource; /// 基线表示参考线,用于表示 循环走到了哪个节点 - (void)moveBaseline1ToIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void(^)(BOOL finished))completion; - (void)moveBaseline2ToIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void(^)(BOOL finished))completion; /// 将某个位置的元素移动到另一个位置 比如 array[toIndex] = array[index] - (void)moveElementAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion; /// 将某一个位置的元素移动到缓冲区,比如 int temp = array[index] - (void)moveElementToCacheAtIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void(^)(BOOL finished))completion; - (void)removeElementFromCacheWithDuration:(NSTimeInterval)duration completion:(void(^)(BOOL finished))completion; /// 交换其中两个元素的位置 比如 int temp = array[index1];array[index1] = array[index2];array[index2] = temp; - (void)exchangeElementAtIndex:(NSInteger)index1 withElementAtIndex:(NSInteger)index2 duration:(NSTimeInterval)duration completion:(void(^)(BOOL finished))completion; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortView.m ================================================ // // STASortView.m // STBasic // // Created by SunJiangting on 13-11-2. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STASortView.h" const NSInteger kSTSortElementTagOffset = 100; @interface STASortView () @property(nonatomic, strong) NSMutableArray *elementViewArray; @property(nonatomic, strong) UIView *baseline1; @property(nonatomic, strong) UIView *baseline2; @property(nonatomic, assign) CGFloat baseWidth; @property(nonatomic, weak) UIView *cacheView; - (UIView *)viewAtIndex:(NSInteger)index; - (CGFloat)frameXAtIndex:(NSInteger)index; @end @implementation STASortView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.factor = 5; self.elementViewArray = [NSMutableArray arrayWithCapacity:5]; self.baseline1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2, CGRectGetHeight(frame))]; self.baseline1.backgroundColor = [UIColor blueColor]; [self addSubview:self.baseline1]; self.baseline2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2, CGRectGetHeight(frame))]; self.baseline2.backgroundColor = [UIColor greenColor]; [self addSubview:self.baseline2]; } return self; } - (void)layoutSubviews { [super layoutSubviews]; if (self.elementViewArray.count == 0) { return; } CGRect frame = self.frame; int width = CGRectGetWidth(self.bounds) / self.elementViewArray.count; self.baseWidth = width; self.baseline1.frame = CGRectMake(0, 0, 2, CGRectGetHeight(frame)); self.baseline2.frame = CGRectMake(0, 0, 2, CGRectGetHeight(frame)); [self.elementViewArray enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) { CGRect frame = subview.frame; frame.origin.x = (idx + 0.5) * width; frame.origin.y = CGRectGetHeight(self.bounds) - frame.size.height; frame.size.width = MIN(30, width - 10); subview.frame = frame; }]; } - (void)reloadSortDataSource:(NSArray *)dataSource { [self.elementViewArray enumerateObjectsUsingBlock:^(UIView *subView, NSUInteger idx, BOOL *stop) { [subView removeFromSuperview]; }]; [self.elementViewArray removeAllObjects]; int width = CGRectGetWidth(self.bounds) / dataSource.count; self.baseWidth = width; self.baseline1.frame = CGRectMake(0.5 * width, 0, 2, CGRectGetHeight(self.bounds)); self.baseline2.frame = CGRectMake(0.5 * width, 0, 2, CGRectGetHeight(self.bounds)); [dataSource enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { CGFloat height = [obj intValue] * self.factor; CGRect frame = CGRectZero; frame.origin = CGPointMake((idx + 0.5) * width, CGRectGetHeight(self.bounds) - height); CGFloat w = MIN(30, width - 10); frame.size = CGSizeMake(w, height); UIView *view = [[UIView alloc] initWithFrame:frame]; view.backgroundColor = [UIColor blackColor]; view.tag = idx + kSTSortElementTagOffset; [self addSubview:view]; [self.elementViewArray addObject:view]; }]; } /// 基线表示参考线,用于表示 循环走到了哪个节点 - (void)moveBaseline1ToIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { CGFloat left = [self frameXAtIndex:index]; CGRect frame = self.baseline1.frame; frame.origin.x = left; [UIView animateWithDuration:duration animations:^{ self.baseline1.frame = frame; } completion:^(BOOL finished) { self.baseline1.frame = frame; if (completion) { completion(finished); } }]; } - (void)moveBaseline2ToIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { CGFloat left = [self frameXAtIndex:index]; CGRect frame = self.baseline2.frame; frame.origin.x = left; [UIView animateWithDuration:duration animations:^{ self.baseline2.frame = frame; } completion:^(BOOL finished) { self.baseline2.frame = frame; if (completion) { completion(finished); } }]; } /// 将某个位置的元素移动到另一个位置 比如 array[toIndex] = array[index] - (void)moveElementAtIndex:(NSInteger)index toIndex:(NSInteger)toIndex duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { UIView *subview = [self viewAtIndex:index]; CGFloat left = [self frameXAtIndex:toIndex]; CGRect frame = subview.frame; frame.origin.x = left; frame.origin.y = CGRectGetHeight(self.bounds) - CGRectGetHeight(subview.bounds); subview.tag = toIndex + kSTSortElementTagOffset; self.cacheView.tag = index + kSTSortElementTagOffset; [UIView animateWithDuration:duration animations:^{ subview.frame = frame; } completion:^(BOOL finished) { subview.frame = frame; if (completion) { completion(finished); } }]; } /// 将某一个位置的元素移动到缓冲区,比如 int temp = array[index] - (void)moveElementToCacheAtIndex:(NSInteger)index duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { UIView *subview = [self viewAtIndex:index]; CGRect frame = subview.frame; frame.origin.y = 0; [UIView animateWithDuration:duration animations:^{ subview.frame = frame; } completion:^(BOOL finished) { subview.frame = frame; if (completion) { completion(finished); } }]; self.cacheView = subview; } - (void)removeElementFromCacheWithDuration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { CGRect frame = self.cacheView.frame; frame.origin.y = CGRectGetHeight(self.bounds) - CGRectGetHeight(self.cacheView.frame); frame.origin.x = [self frameXAtIndex:(self.cacheView.tag - kSTSortElementTagOffset)]; [UIView animateWithDuration:duration animations:^{ self.cacheView.frame = frame; } completion:^(BOOL finished) { self.cacheView.frame = frame; completion(finished); }]; self.cacheView = nil; } /// 交换其中两个元素的位置 比如 int temp = array[index1];array[index1] = array[index2];array[index2] = temp; - (void)exchangeElementAtIndex:(NSInteger)index1 withElementAtIndex:(NSInteger)index2 duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion { UIView *subview1 = [self viewAtIndex:index1]; UIView *subview2 = [self viewAtIndex:index2]; CGRect frame1 = subview1.frame; CGRect frame2 = subview2.frame; frame1.origin.x = [self frameXAtIndex:index2]; frame2.origin.x = [self frameXAtIndex:index1]; subview1.tag = index2 + kSTSortElementTagOffset; subview2.tag = index1 + kSTSortElementTagOffset; [UIView animateWithDuration:duration animations:^{ subview1.frame = frame1; subview2.frame = frame2; } completion:^(BOOL finished) { subview1.frame = frame1; subview2.frame = frame2; if (completion) { completion(finished); } }]; } - (UIView *)viewAtIndex:(NSInteger)index { return [self viewWithTag:(index + kSTSortElementTagOffset)]; } - (CGFloat)frameXAtIndex:(NSInteger)index { return (index + 0.5) * self.baseWidth; } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortViewController.h ================================================ // // STASortViewController.h // STBasic // // Created by SunJiangting on 13-11-1. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STASortDefines.h" #import "STDViewController.h" typedef enum STArraySortType { STArraySortTypeBubbleSort = 1, STArraySortTypeSelectSort = 2, STArraySortTypeInsertSort = 3, STArraySortTypeQuickSort = 5, STArraySortTypeMergeSort = 6, // k-路归并排序 } STArraySortType; @interface STASortViewController : STDViewController @property (nonatomic, assign) STArraySortType arraySortType; @property (nonatomic, strong) NSArray *sortArray; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Algorithm/STASortViewController.m ================================================ // // STASortViewController.m // STBasic // // Created by SunJiangting on 13-11-1. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STASortViewController.h" #import "STASortOperation.h" #import "STASortView.h" #import "STACodeViewController.h" @interface STASortViewController () @property(nonatomic, strong) STASortView *sortView; @property(nonatomic, strong) NSOperationQueue *animationQueue; @property(nonatomic, strong) NSMutableArray *sortMutableArray; @end @implementation STASortViewController - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.animationQueue = [[NSOperationQueue alloc] init]; self.animationQueue.maxConcurrentOperationCount = 1; self.hidesBottomBarWhenPushed = YES; } return self; } - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.animationQueue = [[NSOperationQueue alloc] init]; self.animationQueue.maxConcurrentOperationCount = 1; self.hidesBottomBarWhenPushed = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"源码" target:self action:@selector(viewSourceCode:)]; [self.view removeConstraints:self.view.constraints]; self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeRight; STASortView *sortView = STASortView.new; sortView.translatesAutoresizingMaskIntoConstraints = NO; [sortView reloadSortDataSource:self.sortArray]; [self.view addSubview:sortView]; self.sortView = sortView; NSDictionary *dict = @{@"sortView" : self.sortView }; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[sortView]|" options:0 metrics:nil views:dict]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[sortView]|" options:0 metrics:nil views:dict]]; switch (self.arraySortType) { case STArraySortTypeBubbleSort: self.navigationItem.title = @"冒泡排序"; break; case STArraySortTypeSelectSort: self.navigationItem.title = @"选择排序"; break; case STArraySortTypeInsertSort: self.navigationItem.title = @"插入排序"; break; case STArraySortTypeQuickSort: self.navigationItem.title = @"快速排序"; break; default: break; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self.sortView reloadSortDataSource:self.sortArray]; switch (self.arraySortType) { case STArraySortTypeBubbleSort: [self sortUsingBubbleTypeWithArray:self.sortArray]; break; case STArraySortTypeSelectSort: [self sortUsingSelectTypeWithArray:self.sortMutableArray]; break; case STArraySortTypeInsertSort: [self sortUsingInsertTypeWithArray:self.sortMutableArray]; break; case STArraySortTypeQuickSort: [self sortUsingQuickTypeWithArray:self.sortMutableArray leftOffset:0 rightOffset:self.sortArray.count - 1]; break; default: break; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [self.animationQueue cancelAllOperations]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { } #pragma mark - 插入排序 - (void)sortUsingInsertTypeWithArray:(NSMutableArray *)array { NSInteger count = array.count; for (int i = 1; i < count; i++) { STASortOperation *operation1 = [[STASortOperation alloc] init]; operation1.operationType = STSortOperationTypeMoveBaseline1; operation1.index1 = i; operation1.sortView = self.sortView; [self.animationQueue addOperation:operation1]; id objI = [array objectAtIndex:i], objJ; int j = i; STASortOperation *operation2 = [[STASortOperation alloc] init]; operation2.operationType = STSortOperationTypeMoveBaseline2; operation2.index2 = j; operation2.sortView = self.sortView; [self.animationQueue addOperation:operation2]; STASortOperation *operation3 = [[STASortOperation alloc] init]; operation3.operationType = STSortOperationTypeCacheUpElement; operation3.index1 = j; operation3.sortView = self.sortView; [self.animationQueue addOperation:operation3]; while (j > 0 && [(objJ = [array objectAtIndex:j - 1])intValue] > [objI intValue]) { [array replaceObjectAtIndex:j withObject:objJ]; STASortOperation *operation4 = [[STASortOperation alloc] init]; operation4.operationType = STSortOperationTypeMoveElement; operation4.index1 = j - 1; operation4.index2 = j; operation4.sortView = self.sortView; [self.animationQueue addOperation:operation4]; j--; STASortOperation *operation5 = [[STASortOperation alloc] init]; operation5.operationType = STSortOperationTypeMoveBaseline2; operation5.index2 = j; operation5.sortView = self.sortView; [self.animationQueue addOperation:operation5]; } [array replaceObjectAtIndex:j withObject:objI]; STASortOperation *operation6 = [[STASortOperation alloc] init]; operation6.operationType = STSortOperationTypeCacheDownElement; operation6.sortView = self.sortView; [self.animationQueue addOperation:operation6]; } } #pragma mark - 选择排序 - (void)sortUsingSelectTypeWithArray:(NSMutableArray *)array { NSInteger count = array.count; for (int i = 0; i < count; i++) { STASortOperation *operation1 = [[STASortOperation alloc] init]; operation1.operationType = STSortOperationTypeMoveBaseline1; operation1.index1 = i; operation1.sortView = self.sortView; [self.animationQueue addOperation:operation1]; for (int j = i; j < count; j++) { STASortOperation *operation2 = [[STASortOperation alloc] init]; operation2.operationType = STSortOperationTypeMoveBaseline2; operation2.index2 = j; operation2.sortView = self.sortView; [self.animationQueue addOperation:operation2]; id objI = [array objectAtIndex:i]; id objJ = [array objectAtIndex:j]; if ([objI intValue] > [objJ intValue]) { [array exchangeObjectAtIndex:i withObjectAtIndex:j]; STASortOperation *operation3 = [[STASortOperation alloc] init]; operation3.operationType = STSortOperationTypeExchangeElement; operation3.index1 = i; operation3.index2 = j; operation3.sortView = self.sortView; [self.animationQueue addOperation:operation3]; } } } } #pragma mark - 快速排序 - (void)sortUsingQuickTypeWithArray:(NSMutableArray *)array leftOffset:(NSInteger)left rightOffset:(NSInteger)right { if (left < right) { id key = [array objectAtIndex:left]; STASortOperation *operation0 = [[STASortOperation alloc] init]; operation0.operationType = STSortOperationTypeCacheUpElement; operation0.index1 = left; operation0.sortView = self.sortView; [self.animationQueue addOperation:operation0]; NSInteger low = left; NSInteger high = right; STASortOperation *operation1 = [[STASortOperation alloc] init]; operation1.operationType = STSortOperationTypeMoveBaseline1; operation1.index1 = low; operation1.sortView = self.sortView; [self.animationQueue addOperation:operation1]; STASortOperation *operation2 = [[STASortOperation alloc] init]; operation2.operationType = STSortOperationTypeMoveBaseline2; operation2.index2 = high; operation2.sortView = self.sortView; [self.animationQueue addOperation:operation2]; while (low < high) { while (low < high && [[array objectAtIndex:high] intValue] >= [key intValue]) { high--; STASortOperation *operation3 = [[STASortOperation alloc] init]; operation3.operationType = STSortOperationTypeMoveBaseline2; operation3.index2 = high; operation3.sortView = self.sortView; [self.animationQueue addOperation:operation3]; } [array replaceObjectAtIndex:low withObject:[array objectAtIndex:high]]; STASortOperation *operation5 = [[STASortOperation alloc] init]; operation5.operationType = STSortOperationTypeMoveElement; operation5.index1 = high; operation5.index2 = low; operation5.sortView = self.sortView; [self.animationQueue addOperation:operation5]; while (low < high && [[array objectAtIndex:low] intValue] <= [key intValue]) { low++; STASortOperation *operation6 = [[STASortOperation alloc] init]; operation6.operationType = STSortOperationTypeMoveBaseline1; operation6.index1 = low; operation6.sortView = self.sortView; [self.animationQueue addOperation:operation6]; } [array replaceObjectAtIndex:high withObject:[array objectAtIndex:low]]; STASortOperation *operation8 = [[STASortOperation alloc] init]; operation8.operationType = STSortOperationTypeMoveElement; operation8.index1 = low; operation8.index2 = high; operation8.sortView = self.sortView; [self.animationQueue addOperation:operation8]; } [array replaceObjectAtIndex:low withObject:key]; STASortOperation *operation9 = [[STASortOperation alloc] init]; operation9.operationType = STSortOperationTypeCacheDownElement; operation9.index1 = left; operation9.index2 = low; operation9.sortView = self.sortView; [self.animationQueue addOperation:operation9]; [self sortUsingQuickTypeWithArray:array leftOffset:left rightOffset:low - 1]; [self sortUsingQuickTypeWithArray:array leftOffset:low + 1 rightOffset:right]; } } #pragma mark - 冒泡排序 - (void)sortUsingBubbleTypeWithArray:(NSArray *)array { NSMutableArray *sortArray = [NSMutableArray arrayWithArray:array]; BOOL exchanged = YES; NSInteger count = sortArray.count; for (int i = 0; i < count - 1 && exchanged; i++) { exchanged = NO; STASortOperation *operation0 = [[STASortOperation alloc] init]; operation0.operationType = STSortOperationTypeMoveBaseline1; operation0.index1 = i; operation0.sortView = self.sortView; [self.animationQueue addOperation:operation0]; for (int j = 0; j < (count - 1 - i); j++) { STASortOperation *operation1 = [[STASortOperation alloc] init]; operation1.operationType = STSortOperationTypeMoveBaseline2; operation1.index2 = j; operation1.sortView = self.sortView; [self.animationQueue addOperation:operation1]; id obj0 = [sortArray objectAtIndex:j]; id obj1 = [sortArray objectAtIndex:j + 1]; if ([obj0 intValue] > [obj1 intValue]) { exchanged = YES; /// 需要交换 obj0,obj1 [sortArray exchangeObjectAtIndex:j withObjectAtIndex:j + 1]; STASortOperation *operation3 = [[STASortOperation alloc] init]; operation3.operationType = STSortOperationTypeExchangeElement; operation3.index1 = j; operation3.index2 = j + 1; operation3.sortView = self.sortView; [self.animationQueue addOperation:operation3]; } } } } #pragma mark - 归并排序 - (void)sortUsingMergeTypeWithArray:(NSArray *)array { } - (void)mergeArray:(NSArray *)array withStartIndex:(NSInteger)left midIndex:(NSInteger)mid endIndex:(NSInteger)right toResultArray:(NSMutableArray *)results { } - (void)setSortArray:(NSArray *)sortArray { self.sortMutableArray = [NSMutableArray arrayWithArray:sortArray]; _sortArray = sortArray; } - (void)viewSourceCode:(id)sender { STACodeViewController *viewController = [[STACodeViewController alloc] initWithNibName:nil bundle:nil]; viewController.algorithmType = (STAlgorithmType)self.arraySortType; [self.st_navigationController pushViewController:viewController animated:YES]; } - (void)logArray:(NSArray *)array { [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { printf("%d ", [obj intValue]); }]; printf("\n"); } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STDBookViewController.h ================================================ // // STDBookViewController.h // STKitDemo // // Created by SunJiangting on 13-12-31. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDViewController.h" @protocol STDBookViewControllerDelegate - (void)backViewController; - (void)navigationBarVisibleDidChangeTo:(BOOL)currentVisible; @end @interface STDBookViewController : STDViewController @property (nonatomic, assign) NSInteger page; @property (nonatomic, assign) NSInteger total; @property (nonatomic, retain) NSString *content; @property (nonatomic, assign) BOOL preferredNavigationBarHidden; @property (nonatomic, weak) id delegate; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STDBookViewController.m ================================================ // // STDBookViewController.m // STKitDemo // // Created by SunJiangting on 13-12-31. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDBookViewController.h" #import "STRichView.h" @interface STDBookViewController () { } @property(nonatomic, strong) STRichView *richView; @property(nonatomic, strong) UIButton *backButton; @property(nonatomic, strong) UIButton *touchedButton; @end @implementation STDBookViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.hidesBottomBarWhenPushed = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonCustomItem:STBarButtonCustomItemBack target:self action:@selector(backActionFired:)]; UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; titleLabel.backgroundColor = [UIColor clearColor]; titleLabel.font = [UIFont systemFontOfSize:14.]; titleLabel.textColor = [UIColor st_colorWithRGB:0xFF7300]; titleLabel.text = [NSString stringWithFormat:@"第%ld页 共%ld页", (long)(self.page + 1), (long)self.total]; titleLabel.textAlignment = NSTextAlignmentCenter; self.navigationItem.titleView = titleLabel; self.navigationItem.rightBarButtonItem = nil; CGFloat delta = 0; if (STGetSystemVersion() >= 7) { delta = 20; } CGRect frame = self.view.bounds; frame.origin.y = delta; frame.size.height -= delta; self.richView = [[STRichView alloc] initWithFrame:frame]; self.richView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.richView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:self.richView]; self.richView.text = self.content; self.touchedButton = [UIButton buttonWithType:UIButtonTypeCustom]; CGFloat width = CGRectGetWidth(self.view.bounds); self.touchedButton.frame = CGRectMake(40, 0, width - 80, CGRectGetHeight(self.view.bounds)); self.touchedButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.touchedButton addTarget:self action:@selector(showNavigationViewFired:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.touchedButton]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (self.preferredNavigationBarHidden) { [self hideOverlayAnimated:NO]; } else { [self showOverlayAnimated:NO]; } } - (void)setContent:(NSString *)content { _content = content; if (self.isViewLoaded) { self.richView.text = content; } } - (void)showNavigationViewFired:(id)sender { [self performSelector:@selector(showOverlayIfNeeded) withObject:nil afterDelay:0.0f]; } - (void)showOverlayAnimated:(BOOL)animated { [self st_setNavigationBarHidden:NO animated:animated]; } - (void)hideOverlayAnimated:(BOOL)animated { [self st_setNavigationBarHidden:YES animated:animated]; } - (void)showOverlayIfNeeded { BOOL visible = YES; if (!self.st_navigationBarHidden) { // 需要隐藏 [self hideOverlayAnimated:YES]; visible = NO; } else { // 需要显示 [self showOverlayAnimated:YES]; visible = YES; } if ([self.delegate respondsToSelector:@selector(navigationBarVisibleDidChangeTo:)]) { [self.delegate navigationBarVisibleDidChangeTo:visible]; } } - (void)backActionFired:(id)sender { if ([self.delegate respondsToSelector:@selector(backViewController)]) { [self.delegate backViewController]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STDReaderViewController.h ================================================ // // STDReaderViewController.h // STKitDemo // // Created by SunJiangting on 13-12-31. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDReaderViewController : STDViewController - (instancetype)initWithContentsOfFile:(NSString *)path; - (instancetype)initWithString:(NSString *)string; @property (nonatomic, strong) UIPageViewController *pageViewController; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STDReaderViewController.m ================================================ // // STDReaderViewController.m // STKitDemo // // Created by SunJiangting on 13-12-31. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDReaderViewController.h" #import "STDBookViewController.h" @interface STDReaderViewController () @property(nonatomic, strong) NSString *book; @property(atomic, strong) NSArray *pages; @property(nonatomic, assign) long long offset; @end @implementation STDReaderViewController - (instancetype)initWithContentsOfFile:(NSString *)path { if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { path = [[NSBundle mainBundle] pathForResource:@"book" ofType:@"txt"]; ; } NSString *book = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; return [self initWithString:book]; } - (instancetype)initWithString:(NSString *)string { self = [super initWithNibName:nil bundle:nil]; if (self) { self.book = string; self.st_navigationBarHidden = YES; self.hidesBottomBarWhenPushed = YES; } return self; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { return [self initWithContentsOfFile:nil]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. CGRect frame = self.view.bounds; self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]; self.pageViewController.view.backgroundColor = [UIColor clearColor]; self.view.backgroundColor = [UIColor st_colorWithRGB:0x1C222D]; self.pageViewController.view.frame = frame; [self addChildViewController:self.pageViewController]; [self.view addSubview:self.pageViewController.view]; [self.pageViewController didMoveToParentViewController:self]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (self.pages.count == 0) { [self reloadBook]; } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - UIPageViewControllerDataSource - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController { if (![viewController isKindOfClass:[STNavigationController class]]) { return nil; } STNavigationController *oldNavigationController = (STNavigationController *)viewController; STDBookViewController *oldViewController = (STDBookViewController *)oldNavigationController.viewControllers[0]; NSInteger page = oldViewController.page; if (page == 0) { UIGestureRecognizer *gestureRecognizer = self.st_navigationController.interactivePopGestureRecognizer; gestureRecognizer.enabled = YES; return nil; } NSRange prevRange = NSRangeFromString([self.pages objectAtIndex:page - 1]); NSString *content = [self.book substringWithRange:prevRange]; self.offset = prevRange.location; STDBookViewController *previousViewController = STDBookViewController.new; STNavigationController *navigationController = [[STNavigationController alloc] initWithRootViewController:previousViewController]; previousViewController.preferredNavigationBarHidden = YES; navigationController.interactivePopGestureRecognizer.enabled = NO; previousViewController.delegate = self; previousViewController.page = page - 1; previousViewController.total = self.pages.count; previousViewController.content = content; /// 往前翻的话,只有第0页支持左滑 UIGestureRecognizer *gestureRecognizer = self.st_navigationController.interactivePopGestureRecognizer; if (page == 1) { gestureRecognizer.enabled = YES; } else { gestureRecognizer.enabled = NO; } return navigationController; } - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController { if (![viewController isKindOfClass:[STNavigationController class]]) { return nil; } STNavigationController *newerNavigationController = (STNavigationController *)viewController; STDBookViewController *newerViewController = (STDBookViewController *)newerNavigationController.viewControllers[0]; NSInteger page = newerViewController.page; if (page == self.pages.count - 1 || page >= self.pages.count) { if (page == 0 && self.pages.count == 0) { UIGestureRecognizer *gestureRecognizer = self.st_navigationController.interactivePopGestureRecognizer; gestureRecognizer.enabled = YES; } return nil; } NSRange nextRange = NSRangeFromString([self.pages objectAtIndex:page + 1]); NSString *content = [self.book substringWithRange:nextRange]; self.offset = nextRange.location; STDBookViewController *nextViewController = STDBookViewController.new; STNavigationController *navigationController = [[STNavigationController alloc] initWithRootViewController:nextViewController]; navigationController.interactivePopGestureRecognizer.enabled = NO; nextViewController.preferredNavigationBarHidden = YES; nextViewController.delegate = self; nextViewController.page = page + 1; nextViewController.total = self.pages.count; nextViewController.content = content; /// 往后翻的话,都不支持左滑收拾 UIGestureRecognizer *gestureRecognizer = self.st_navigationController.interactivePopGestureRecognizer; gestureRecognizer.enabled = NO; return navigationController; } #pragma mark - UIPageViewController delegate methods /* - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed { } */ - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { // Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine // position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here. return UIPageViewControllerSpineLocationMin; } #pragma mark - reloadBook - (void)paginationBookCompletion:(void (^)(BOOL finished))completion { NSDictionary *attributes = [[STThemeManager currentTheme] themeValueForKey:@"BookTextAttributes" whenContainedIn:NSClassFromString(@"STRichView")]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ CGSize size = self.pageViewController.view.bounds.size; CGFloat delta = (STGetSystemVersion() >= 7) ? 20 : 0; size.height -= delta; self.pages = [self.book st_paginationWithAttributes:attributes constrainedToSize:size]; dispatch_async(dispatch_get_main_queue(), ^{ if (self.pages.count == 0) { completion(NO); } else { completion(YES); } }); }); } - (void)reloadBook { [STIndicatorView showInView:self.view animated:NO]; [self paginationBookCompletion:^(BOOL finished) { if (finished) { NSUInteger page = [self pageOfOffset:self.offset]; NSRange range = NSRangeFromString([self.pages objectAtIndex:page]); NSString *content = [self.book substringWithRange:range]; STDBookViewController *bookViewController = STDBookViewController.new; STNavigationController *navigationController = [[STNavigationController alloc] initWithRootViewController:bookViewController]; bookViewController.preferredNavigationBarHidden = NO; bookViewController.delegate = self; bookViewController.page = page; bookViewController.total = self.pages.count; bookViewController.content = content; self.pageViewController.delegate = self; self.pageViewController.dataSource = self; [self.pageViewController setViewControllers:@[ navigationController ] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; } [STIndicatorView hideInView:self.view animated:YES]; }]; } - (NSUInteger)pageOfOffset:(long long)offset { __block NSUInteger pageIndex = 0; [self.pages enumerateObjectsUsingBlock:^(NSString *page, NSUInteger idx, BOOL *stop) { NSRange range = NSRangeFromString(page); if (range.location <= offset && (range.location + range.length > offset)) { pageIndex = idx; *stop = YES; } }]; return pageIndex; } #pragma mark - Rotate - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; [self reloadBook]; } #pragma mark - STDBookViewControllerDelegate - (void)backViewController { [self.st_navigationController popViewControllerAnimated:YES]; } - (void)navigationBarVisibleDidChangeTo:(BOOL)currentVisible { UIGestureRecognizer *gestureRecognizer = self.st_navigationController.interactivePopGestureRecognizer; NSArray *viewControllers = self.pageViewController.viewControllers; BOOL firstPage = NO; if (viewControllers.count > 0) { STNavigationController *navigationController = viewControllers[0]; NSArray *array1 = navigationController.viewControllers; if (array1.count > 0) { STDBookViewController *bookViewController = (STDBookViewController *)navigationController.viewControllers[0]; firstPage = bookViewController.page == 0; } } if (currentVisible || firstPage) { gestureRecognizer.enabled = YES; } else { gestureRecognizer.enabled = NO; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STRichView.h ================================================ // // STRichView.h // STKitDemo // // Created by SunJiangting on 13-6-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @interface STRichView : UIView @property(nonatomic, strong) UIColor *foregroundColor; @property(nonatomic, strong) NSDictionary *attributes; @property(nonatomic, copy) NSString *text; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/STRichView.m ================================================ // // STRichView.m // STKitDemo // // Created by SunJiangting on 13-6-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STRichView.h" #import #import @interface STRichView () @end @implementation STRichView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.foregroundColor = [[STThemeManager currentTheme] themeValueForKey:@"BookTextColor" whenContainedIn:[self class]]; self.attributes = [[STThemeManager currentTheme] themeValueForKey:@"BookTextAttributes" whenContainedIn:[self class]]; } return self; } - (id) initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { // Initialization code self.foregroundColor = [[STThemeManager currentTheme] themeValueForKey:@"BookTextColor" whenContainedIn:[self class]]; self.attributes = [[STThemeManager currentTheme] themeValueForKey:@"BookTextAttributes" whenContainedIn:[self class]]; } return self; } - (void) setText:(NSString *)text { [self willChangeValueForKey:@"text"]; _text = [text copy]; [self setNeedsDisplay]; [self didChangeValueForKey:@"text"]; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { if (!self.text) { return; } CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1.0, -1.0); NSDictionary *basicAttributes = self.attributes; NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary:basicAttributes]; [attributes setValue:(id)self.foregroundColor forKey:(id)kCTForegroundColorAttributeName]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:self.text attributes:attributes]; UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:rect]; CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedString)); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), bezierPath.CGPath, NULL); CTFrameDraw(frame, context); CFRelease(frame); CFRelease(framesetter); } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/BookReader/book.txt ================================================ 令狐冲和盈盈出得山谷,行了半日,来到一处市镇,到一家面店吃面。令狐冲筷子上挑起长长几根面条,笑吟吟的道:“我和你还没拜堂成亲……”盈盈登时羞得满脸通红,嗔道:“谁和你拜堂成亲了?”令狐冲微笑道:“将来总是要成亲的。你如不愿,我捉住了你拜堂。”盈盈似笑非笑的道:“在山谷中倒是乖乖的,一出来就来说这些不正经的疯话。”令狐冲笑道:“终身大事,最是正经不过。盈盈,那日在山谷之中,我忽然想起,日后和你做了夫妻,不知生几个儿子好。”盈盈站起身来,秀眉微蹙,道:“你再说这些话,我不跟你一起去恒山啦。”令狐冲笑道:“好,好,我不说,我不说。因为那山谷中有许多桃树,倒像是个桃谷,要是有六个小鬼在其间鬼混,岂不是变了小桃谷六仙?”盈盈坐了下来,问道:“哪里来六个小鬼?”一语出口,便即省悟,又是令狐冲在说风话,白了他一眼,低头吃面,心中却十分甜蜜。‘令狐冲道:“我和你同上恒山,有些心地龌龊之徒,还以为我和你已成夫妻,在他自己的脏肚子里胡说八道,只怕你不高兴。”这一言说中了盈盈的心事,道:“正是。好在我现下跟你都穿了乡下庄稼人的衣衫,旁人未必认得出。”令狐冲道:“你这般花容月貌,不论如何改扮,总是惊世骇俗。旁人一见,心下暗暗喝采:‘嘿,好一个美貌乡下大姑娘,怎地跟着这一个傻不楞登的臭小子,岂不是一朵鲜花插在牛粪上了?’待得仔细多看上几眼,不免认出这朵鲜花原来是日月神教的任大小姐,这堆牛粪呢,自然是大蒙任小姐垂青的令狐冲了。”盈盈笑道:“阁下大可不用如此谦虚。”令狐冲道:“我想,咱们这次去恒山,我先乔装成个毫不起眼之人,暗中察看。如果太平无事,我便独自现身,将掌门之位传了给人,然后和你在甚么秘密地方相会,一同下山,神不知,鬼不觉,岂不是好?”   盈盈听他这么说,知他是体贴自己,甚是喜欢,笑道:“那好极了,不过你上恒山去,尤其是去见那些师太,只好自己剃光了头,也扮成个师太,旁人才不起疑。冲哥,来,我就给你乔装改扮,你扮成个小尼姑,只怕倒也俊俏得紧。”令狐冲连连摇手,道:“不成,不成。一见尼姑,逢赌必输。令狐冲扮成尼姑,今后可倒足了大霉,那决计不成。”盈盈笑道:“大丈夫能屈能伸,却偏有这许多忌讳。我非剃光你的头不可。”令狐冲笑道:“扮尼姑倒也不必了,但要上见性峰,扮女人却是势在必行。只是我一开口说话,就给听出来是男人。我倒有个计较,你可记得恒山磁窑口翠屏山悬空寺中的一个人吗?”盈盈一沉吟,拍手道:“妙极,妙极!悬空寺中有个又聋又哑的仆妇,咱们在悬空寺上打得天翻地覆,她半点也听不到。问她甚么,她只是呆呆的瞧着你。你想扮成这人?”令狐冲道:“正是。”盈盈笑道:“好,咱们去买衣衫,就给你乔装改扮。”盈盈用二两银子向一名乡妇买了一头长发,细心梳好了,装在令狐冲头上,再让他换上农妇装束,宛然便是个女子,再在脸上涂上黄粉,画上七八粒黑痣,右腮边贴了块膏药。令狐冲对镜一看,连自己也认不出来。盈盈笑道:“外形是像了,神气却还不似,须得装作痴痴呆呆、笨头笨脑的模样。”令狐冲笑道:“痴痴呆呆的神气最是容易不过,那压根儿不用装,笨头笨脑,原是令狐冲的本色。”盈盈道:“最要紧的是,旁人倘若突然在你身后大声吓你,千万不能露出马脚。”一路之上,令狐冲便装作那个又聋又哑的仆妇,先行练习起来。二人不再投宿客店,只在破庙野祠中住宿。盈盈时时在他身后突发大声,令狐冲竟充耳不闻。不一日,到了恒山脚下,约定三日后在悬空寺畔聚头。令狐冲独自上见性峰去,盈盈便在附近游山玩水。   到得见性峰峰顶,已是黄昏时分,令狐冲寻思:“我若径行入庵,仪清、郑萼、仪琳师妹她们心细的人多,察看之下,不免犯疑。我还是暗中窥探的好。”当下找个荒僻的山洞,睡了一觉,醒来时月已天中,这才奔往见性峰主席无色庵。刚走近主庵,便听得铮铮铮数下长剑互击之声,令狐冲心中一动:“怎么来了敌人?”一摸身边暗藏的短剑,纵身向剑声处奔去。兵刃撞击声从无色庵旁十余丈外的一间瓦屋中发出,瓦屋窗中透出灯光。令狐冲奔到屋旁,但听兵刃撞击声更加密了,凑眼从窗缝中一张,登时放心,原来是仪和与仪琳两师姊妹正在练剑,仪清和郑萼二人站着旁观。仪和与仪琳所使的,正是自己先前所授、学自华山思过崖后洞石壁上的恒山剑法。二人剑法已颇为纯熟。斗到酣处,仪和出剑渐快,仪琳略一疏神,仪和一剑刺出,直指前胸,仪琳回剑欲架,已然不及,“啊”的一声轻叫。仪和长剑的剑尖已指在她心口,微笑道:“师妹,你又输了。”仪琳甚是惭愧,低头道:“小妹练来练去,总是没甚么进步。”仪和道:“比之上次已有进步了,咱们再来过。”长剑在空中虚劈一招。仪清道:“小师妹累啦,就和郑师妹去睡罢,明日再练不迟。”仪琳道:“是。”收剑入鞘,向仪和、仪清行礼作别,拉了郑萼的手推门出外。她转过身时,令狐冲见她容色憔悴,心想:“这个小师妹心中总是不快乐。”仪和掩上了门,和仪清二人相对摇了摇头,待听得仪琳和郑萼脚步声已远,说道:“我看小师妹总是静不下心来。心猿意马,那是咱们修道人的大忌,不知怎生劝劝她才好。”仪清道:“劝是很难劝的,总须自悟。”仪和道:“我知道她为甚么不能心静,她心中老是想着……”仪清摇手道:“佛门清净之地,师姊别说这等话。若不是为了急于报师父的大仇,让她慢慢自悟,原亦不妨。”   仪和道:“师父常说:世上万事皆须随缘,半分勉强不得;尤其收束心神,更须循序渐进,倘若着意经营,反易堕入魔障。我看小师妹外和内热,乃是性情中人,身入空门,于她实不相宜。”仪清叹了口气,道:“这一节我也何尝没想到,只是……只是一来我派终须有佛门中人接掌门户,令狐师兄曾一再声言,他代掌门户只是一时的权宜之计;更要紧的是,岳不群这恶贼害死我们师父、师叔……”   令狐冲听到这里,大吃一惊:“怎地是我师父害死她们的师父、师叔?”只听仪清续道:“不报这深恨大仇,咱们做弟子的寝食难安。”仪和道:“我只有比你更心急,好,赶明儿我加紧督促她练剑便了。”仪清道:“常言道:欲速则不达,却别逼得她太过狠了。我看小师妹近日精神越来越差。”仪和道:“是了。”两师姊妹收起兵刃,吹灭灯火,入房就寝。   令狐冲悄立窗外,心下疑思不解:“她们怎么说我师父害死了她们的师父、师叔?又为甚么为报师仇,为了有人接掌恒山门户,便须督促仪琳小师妹日夜勤练剑法?”凝思半晌,不明其理,慢慢走开,心想:“日后询问仪和、仪清两位师姊便是。”猛见地下自己的影子缓缓晃动,抬头望月,只见月亮斜挂树梢,心中陡然闪过一个念头,险些叫出声来,心道:“我早该想到了。为甚么她们早就明白此事,我却一直没想到?”闪到近旁小屋的墙外,靠墙而立,以防恒山派中有人见到自己身影,这才静心思索,回想当日在少林寺中定闲、定逸两位师太毙命的情状:其时定逸师太已死,定闲师太嘱咐我接掌恒山门户之后,便即逝去,言语中没显露害死她们的凶手是谁。检视之下,二位师太身上并无伤痕,并非受了内伤,更不是中毒,何以致死,甚是奇怪,只是不便解开她们衣衫,详查伤处。后来离少林寺出来,在雪野山洞之中,盈盈说在少林寺时曾解开二位师太的衣衫查伤,见到二人心口都有一粒钉孔大的红点,是被人用针刺死。当时我跳了起来,说道:“毒针?武林之中,有谁是使毒针的?”盈盈说道:“爹爹和向叔叔见闻极广,可是他们也不知道。爹爹又说,这针并非毒针,乃是一件兵刃,刺入要害,致人死命。只是刺入定闲师太心口那一针,略略偏斜了些。”我说:“是了,我见到定闭师太之时,她还没断气。这针既是当胸刺入,那就并非暗算,而是正面交锋。那么害死两位师太的,定是武功绝顶的高手。”盈盈道:“我爹爹也这么说。既有了这条线索,要找到凶手,想亦不难。”当时我伸掌在山洞石壁上用力一拍,大声道:“盈盈,我二人有生之年,定当为两位师太报仇雪恨。”盈盈道:“正是。”令狐冲双手反按墙壁,身子不禁发抖,心想:“能使一枚小针而杀害这两位高手师太,若不是练了葵花宝典的,便是练了辟邪剑法的。东方不败一直在黑木崖顶闺房中绣花,不会到少林寺来杀人,以他武功,也决不会针刺定闲师太而一时杀她不了。左冷禅所练的辟邪剑法是假的。那时候林师弟初得剑谱未久,未必已练成剑法,甚至还没得到剑谱……”回想当日在雪地里遇到林平之与岳灵珊的情景,心想:“不错,那时候林平之说话未变雌声,不管他是否已得剑谱,辟邪剑法总是尚未练成。”想到此处,额头上冷汗涔涔而下,那时候能以一枚细针、正面交锋而害死恒山派两大高手,武功却又高不了定闲师太多少,一针不能立时致她死命,那只有岳不群一人。又想起岳不群处心积虑,要做五岳派的掌门,竟能让劳德诺在门下十余年之久,不揭穿他的来历,末了让他盗了一本假剑谱去,由此轻轻易易的刺瞎左冷禅双目。定闲、定逸两位师太极力反对五派合并,岳不群乘机下手将其除去,少了并派的一大阻力,自是在情理之中。定闲师太为甚么不肯吐露害她的凶手是谁?自然由于岳不群是他的师父之故。倘若凶手是左冷禅或东方不败,定闲师太又何以不说?   令狐冲又想到当时在山洞中和盈盈的对话。他在少林寺给岳不群重重踢了一脚,他并未受伤,岳不群腿骨反断,盈盈大觉奇怪。她说她父亲想了半天,也想不出其中原因,令狐冲吸了不少外人的内功,固然足以护体,但必须自加运用方能伤人,不像自己所练成的内功,不须运使,自能将对方攻来的力道反弹出去。此刻想来,岳不群自是故意做作,存心做给左冷禅看的,那条腿若非假断,便是他自己以内力震断,好让左冷禅瞧在眼里,以为他武功不过尔尔,不足为患,便可放手进行并派。左冷禅花了无数心血力气,终于使五派合并,到得头来,却是为人作嫁,给岳不群一伸手就将成果取了去。这些道理本来也不难明,只是他说甚么也不会疑心到师父身上,或许内心深处,早已隐隐想到,但一碰到这念头的边缘,心思立即避开,既不愿去想,也不敢去想,直至此刻听到了仪和、仪清的话,这才无可规避。   自己一生敬爱的师父,竟是这样的人物,只觉人生一切,都是殊无意味,一时打不起精神到恒山别院去查察,便在一处僻静的山坳里躺下睡了。   次日清晨,令狐冲到得通元谷时,天已大明。他走到小溪之旁,向溪水中照映自己改装后的容貌,又细看身上衣衫鞋袜,一无破绽,这才走向别院。他绕过正门,欲从边门入院,刚到门边,便听得一片喧哗之声。   只听得院子里许多人大声喧叫:“真是古怪!他妈的,是谁干的?”“甚么时候干的?怎么神不知,鬼不觉,手脚可真干净利落!”“这几人武功也不坏啊,怎地着了人家道儿,哼也不哼一声?”令狐冲知道发生了怪事,从边门中挨进去,只见院子中和走廊上都站满了人,眼望一株公孙树的树梢。令狐冲抬头一看,大感奇怪,心中的念头也与众人所叫嚷的一般无异,只见树上高高挂着八人,乃是仇松年、张夫人、西宝和尚、玉灵道人这一伙七人,另外一人是“滑不留手”游迅。八人显是都被点了穴道,四肢反缚,吊在树枝上荡来荡去,离地一丈有余,除了随风飘荡,半分动弹不得。八人神色之尴尬,实是世所罕见。两条黑蛇在八人身上蜿蜒游走,那自是“双蛇恶乞”严三星的随身法宝了。这两条蛇盘到严三星身上,倒也没甚么,游到其他七人身上时,这些人气愤羞惭的神色之中,又加上几分害怕厌恶。人丛中跃起一人,正是夜猫子“无计可施”计无施。他手持匕首,纵上树干,割断了吊着“桐柏双奇”的绳索。这两人从空中摔下,那矮矮胖胖的老头子伸手接住,放在地上。片刻之间,计无施将八人都救下来,解开了各人被封的穴道。仇松年等一得自由,立时污言秽语的破口大骂。只见众人都是眼睁睁的瞧着自己,有的微笑,有的惊奇。有人说道:“已!”有人说道:“阴!”有人说道:“小!”有人说道:“命!”张夫人一侧头,只见仇松年等七人额头上都用朱笔写着一个字,有的是“已”,有的是“阴”字,料想自己额头也必有字,当即伸手去抹。祖千秋已推知就里,将八人额头的八个字串起来,说道:“阴谋已败,小心狗命!”余人一听不错,纷纷说道:“阴谋已败,小心狗命!”西宝和尚大声骂道:“甚么阴谋已败,你奶奶的,小心谁的狗命?”玉灵道人忙摇手阻止,在掌心中吐了一大口唾沫,伸手去擦额头的字。祖千秋道:“游兄,不知八位如何中了旁人的暗算,可能赐告吗?”游迅微微一笑,说道:“说来惭愧,在下昨晚睡得甚甜,不知如何,竟给人点了穴道,吊在这高树之上。那下手的恶贼,多半使用‘五更鸡鸣还魂香’之类迷药,否则兄弟本领不济,遭人暗算,那也罢了,像玉灵道长、张夫人这等智勇兼备的人物,如何也着了道儿?”张夫人哼了一声,道:“正是如此。”不愿与旁人多说,忙入内照镜洗脸,玉灵道人等也跟了进去。   群豪议论不休,啧啧称奇,都道:“游迅之言不尽不实。”有人道:“大伙儿数十人在堂内睡觉,若放迷香,该当数十人一起迷倒才是,怎会只迷倒他们几个?”众人猜想那“阴谋已败”的阴谋,不知是何所指,种种揣测都有,莫衷一是。有人道:“不知将这八人倒吊高树的那位高手是谁?”有人笑道:“幸亏桃谷六怪今番没到,否则又有得乐子了。”另一人道:“你怎知不是桃谷六仙干的?这六兄弟古里古怪,多半便是他们做的手脚。”祖千秋摇头道:“不是,不是,决计不是。”先一人道:“祖兄如何得知?”祖千秋笑道:“桃谷六仙武功虽高,肚子里的墨水却有限得很,那‘阴谋’二字,担保他们就不会写。”群豪哈哈大笑,均说言之有理。各人谈论的都是这件趣事,没人对令狐冲这呆头呆脑的仆妇多瞧上一眼。令狐冲心中只是在想:“这八人想搅甚么阴谋?那多半是意欲不利于我恒山派。”这日午后,忽听得有人在外大叫:“奇事,奇事,大家来瞧啊!”群豪涌了出去。令狐冲慢慢跟在后面,只见别院右首里许外有数十人围着,群豪急步奔去。令狐冲走到近处,听得众人正自七张八嘴的议论。有十余人坐在山脚下,面向山峰,显是被点中了穴道,动弹不得,山壁上用黄泥写着八个大字,又是“阴谋已败,小心狗命”。   当下有人将那十余人转过身来,赫然有爱吃人肉的漠北双熊在内。计无施走上前去,在漠北双熊背上推拿了几下,解开了他们哑穴,但余穴不解,仍是让他们动弹不得,说道:“在下有一事不明,可要请教。请问二位到底参与了甚么密谋,大伙儿都想知道。”群豪都道:“对,对!有甚么阴谋,说出来大家听听。”黑熊破口大骂:“操他奶奶的十八代祖宗,有甚么阴谋,阴他妈龟儿子的谋。”祖千秋道:“那么众位是给谁点倒的,总可以说出来让大伙儿听听罢。”白熊道:“老子知道就好了。老子好端端在山边散步,背心一麻,就着了乌龟孙子王八蛋的道儿。是英雄好汉,就该真刀真枪的打上一架,在人家背后偷袭,算甚么人物?”祖千秋道:“两位既不肯说,也就罢了。这件事既已给人揭穿,我看是干不成了,只是大伙儿不免要多留心留心。”有人大声道:“祖兄,他们不肯吐露,就让他们在这山脚边饿上三天三夜。”另一人道:“不错,解铃还由系铃人。你如放了他们,那位高人不免将你怪上了,也将你点倒,吊将起来,可不是玩的。”计无施道:“此言不错。众位兄台,在下不是袖手旁观,实在有点胆寒。”   黑熊、白熊对望了一眼,都大骂起来,只是骂得不着边际,可也不敢公然骂计无施这一干人的祖宗,否则自己动弹不得,对方若要动粗,却无还手之力。   计无施笑着拱拱手,说道:“众位请了。”转身便行。余人围着指指点点,说了一会子话,慢慢都散开了。令狐冲慢慢踱回,刚到院子外,听得里面又有人叫嚷嘻笑。一抬头间,见公孙树上又倒吊着二人,一个是不可不戒田伯光,另一个却是不戒和尚。令狐冲心下大奇:“不戒大师是仪琳小师妹的父亲,田伯光是小师妹的弟子。他二人说甚么也不会来跟恒山派为难。恒山派有难,他们定会奋力援手。怎地也给人吊在树上?”心中原来十分确定的设想,突然间给全部推翻,脑海中闪过一个念头:“不戒大师天真烂漫,与人无许,怎会给人倒吊高树,定是有人和他恶作剧了。要擒住不戒大师,非一人之力可办,多半便是桃谷六仙。”但想到祖千秋先前的言语,说桃谷六仙写不出“阴谋”二字,确也甚是有理。他满腹疑窦,慢慢走进院子去,只见不戒和尚与田伯光身上都垂着一条黄布带子,上面写得有字。不戒和尚身上那条带上写道:“天下第一负心薄幸、好色无厌之徒。”田伯光身上那条带上写道:“天下第一大胆妄为、办事不力之人。”令狐冲第一个念头便是:“这两条带子挂错了。不戒和尚怎会是‘好色无厌之徒’?这‘好色无厌’四字,该当送给田伯光才是。至于‘大胆妄为’四字,送给不戒和尚倒还贴切,他不戒杀,不戒荤,做了和尚,敢娶尼姑,自是大胆妄为之至,不过‘办事不力’,又不知从何说起?”但见两根布带好好的系在二人颈中,垂将下来,又不像是匆忙中挂错了的。群豪指指点点,笑语评论,大家也都说:“田伯光贪花好色,天下闻名,这位大和尚怎能盖得过他?”   计无施与祖千秋低声商议,均觉大是蹊跷,知道不戒和尚和令狐冲交情甚好,须得将二人救下来再说。当下计无施纵身上树,将二人手足上被缚的绳索割断,解开了二人穴道。不戒与田伯光都是垂头丧气,和仇松年、漠北双熊等人破口大骂的情状全然不同。计无施低声问道:“大师怎地也受这无妄之灾?”不成和尚摇了摇头,将布条缓缓解下,对着布条上的字看了半晌,突然间顿足大哭。   这一下变故,当真大出群豪意料之外,众人语声顿绝,都呆呆的瞧着他。只见他双拳捶胸,越哭越伤心。田伯光劝道:“太师父,你也不用难过。咱们失手遭人暗算,定要找了这个人来,将他碎尸万段……”他一言未毕,不戒和尚反手一掌,将他打得直跌出丈许之外,几个踉跄,险些摔倒,半边脸颊登时高高肿起。不戒和尚骂道:“臭贼!咱们给吊在这里,当然是罪有应得,你……你……你好大的胆子。想杀死人家啊。”田伯光不明就里,听太师父如此说,擒住自己之人定是个大有来头的人物,竟连太师父也不敢得罪他半分,只得唯唯称是。不戒和尚呆了一呆,又捶胸哭了起来,突然间反手一掌,又向田伯光打去。田伯光身法极快,身子一侧避开,叫道:“太师父!”不戒和尚一掌没打中,也不再追击,顺手回过掌来,拍的一声,打在院中的一张石凳之上,只击得石屑纷飞。他左手一掌,右手一掌,又哭又叫,越击越用力,十余掌后,双掌上鲜血淋漓,石凳也给他击得碎石乱崩,忽然间喀喇一声,石凳裂为四块。群豪无不骇然,谁也不敢哼上一声,倘若他盛怒之下,找上了自己,一击中头,谁的脑袋能如石凳般坚硬?祖千秋、老头子、计无施三人面面相觑,半点摸不着头脑。田伯光眼见不对,说道:“众位请照看着太师父。我去相请师父。”令狐冲寻思:“我虽已乔装改扮,但仪琳小师妹心细,别要给她瞧出了破绽。”他扮过军官,扮过乡农,但都是男人,这次扮成女人,实在说不出的别扭,心中绝无自信,生怕露出了马脚。当下去躲在后园的一间柴房之中,心想:“漠北双熊等人兀自被封住穴道,猜想计无施、祖千秋等人之意,当是晚间去窃听这些人的谈论。我且好好睡上一觉,半夜里也去听上一听。”耳听得不戒和尚号啕之声不绝,又是惊奇,又是好笑,迷迷糊糊的便即入睡。   醒来时天已入黑,到厨房中去找些冷饭茶来吃了。又等良久,耳听得人声渐寂,于是绕到后山,慢慢踱到漠北双熊等人被困之处,远远蹲在草丛之中,侧耳倾听。不久便听得呼吸声此起彼伏,少说也有二十来人散在四周草木丛中,令狐冲暗暗好笑:“计无施他们想到要来偷听,旁人也想到了,聪明人还真不少。”又想,“计无施毕竟了得,他只解了漠北双熊这两个吃人肉粗胚的哑穴,却不解旁人的哑穴,否则漠北双熊一开口说话,便会给同伙中精明能干之辈制止。”只听得白熊不住口的在詈骂:“他奶奶的,这山边蚊子真多,真要把老子的血吸光了才高兴,我操你臭蚊虫的十八代祖宗。”黑熊笑道:“蚊子只是叮你,却不来叮我,不知是甚么缘故。”白熊骂道:“你的血臭的,连蚊子也不吃。”黑熊笑道:“我宁可血臭,好过给几百只蚊子在身上叮。”白熊又是“直娘贼,龟儿子”的大骂起来。   白熊骂了一会,说道:“穴道解开之后,老子第一个便找夜猫子算帐,把这龟蛋点了穴道,将他大腿上的肉一口口咬下来生吃。”黑熊笑道:“我却宁可吃那些小尼姑们,细皮白肉,嫩得多了。”白熊道:“岳先生吩咐了的,尼姑们要捉到华山去,可不许吃。”黑熊笑道:“几百个尼姑,吃掉三四个,岳先生也不会知道。”令狐冲大吃一惊:“怎么是师父吩咐了的?怎么要他们将恒山派弟子捉到华山去?这个‘大阴谋’,自然是这件事了。可是他们又怎么会听我师父的号令?”   忽听得白熊高声大骂:“乌龟儿子王八蛋!”黑熊怒道:“你不吃尼姑便不吃,干么骂人?”白熊道:“我骂蚊子,又不是骂你。”令狐冲满腹疑团,忽听得背后草丛中脚步声响,有人慢慢走近,心想:“这人别要踏到我身上来才好。”那人对准了他走来,走到他身后,蹲了下来,轻轻拉他衣袖。令狐冲微微一惊:“是谁?难道认了我出来?”回过头来,朦胧月光之下,见到一张清丽绝俗的脸庞,正是仪琳。他又惊又喜,心想:“原来我的行迹早给她识破了。要扮女人,毕竟不像。”仪琳头一侧,小嘴努了努,缓缓站起身来,仍是拉着他衣袖,示意和他到远处说话。令狐冲见她向西行去,便跟在她身后。两人一言不发,径向西行。仪琳沿着一条狭狭的山道,走出了通元谷,忽然说道:“你又听不见人家的说话,挤在这是非之地,那可危险得紧。”她几句话似乎并不是向他而说,只是自言自语。令狐冲一怔,心道:“她说我听不见人家说话,那是甚么意思?她说的是反话,还是真的认我不出?”又想仪琳从来不跟自己说笑,那么多半是认不出了,只见她折而向北,渐渐向着磁窑口走去,转过了一个山坳,来到了一条小溪之旁。仪琳轻声道:“我们老是在这里说话,你可听厌了我的话吗?”跟着轻轻一笑,说道:“你从来就听不见我的话,哑婆婆,倘若你能听见我说话,我就不会跟你说了。”令狐冲听仪琳说得诚挚,知她确是将自己认作了悬空寺中那个又聋又哑的仆妇。他童心大起,心道:“我且不揭破,听她跟我说些甚么。”仪琳牵着他衣袖,走到一株大柳树下的一块长石之旁,坐了下来。令狐冲跟着坐下,侧着身子,背向月光,好教仪琳瞧不见自己的脸,寻思:“难道我真的扮得很像,连仪琳也瞒过了?是了,黑夜之中,只须有三分相似,她便不易分辨。盈盈的易容之术,倒也了得。”仪琳望着天上眉月,幽幽叹了口气。令狐冲忍不住想问:“你小小年纪,为甚么有这许多烦恼?”但终于没出声。仪琳轻声道:“哑婆婆,你真好,我常常拉着你来,向你诉说我的心事,你从来不觉厌烦,总是耐心的等着,让我爱说多少,便说多少。我本来不该这样烦你,但你待我真好,便像我自己亲生的娘一般。我没有娘,倘若我有个妈妈,我敢不敢向她这样说呢?”令狐冲听到她说是倾诉自己心事,觉得不妥,心想:“她要说甚么心事?我骗她吐露内心秘密,可太也对不住她,还是快走的为是。”当即站起身来。仪琳拉住了他袖子,说道:“哑婆婆,你……你要走了吗?”声音中充满失望之情。令狐冲向她望了一眼,只见她神色凄楚,眼光中流露出恳求之意,不由得心下软了,寻思:“小师妹形容憔悴,满腹心事,倘若无处倾诉,老是闷在心里,早晚要生重病。我且听她说说,只要她始终不知是我,也不会害羞。”当下又缓缓坐了下来。仪琳伸手搂住他脖子,说道:“哑婆婆,你真好,就陪我多坐一会儿。你不知道我心中可有多闷。”令狐冲心想:“令狐冲这一生可交了婆婆运,先前将盈盈错认作是婆婆,现下又给仪琳错认是婆婆。我叫了人家几百声婆婆,现在她叫还我几声,算是好人有好报。”   仪琳道:“今儿我爹爹险些儿上吊死了,你知不知道?他给人吊在树上,又给人在身上挂了一根布条儿,说他是‘天下第一负心薄幸,好色无厌之徒’。我爹爹一生,心中就只有我妈妈一人,甚么好色无厌,那是从何说起?那人一定胡里胡涂,将本来要挂在田伯光身上的布条,挂错在爹爹身上了。其实挂错了,拿来掉过来就是,可用不着上吊自尽哪。”令狐冲又是吃惊,又是好笑:“怎么不戒大师要自尽?她说他险些儿上吊死了,那么定是没死。两根布条上写的都不是好话,既然拿了下来,怎么又去掉转来挂在身上?这小师妹天真烂漫,真是不通世务之至。”   仪琳说道:“田伯光赶上见性峰来,要跟我说,偏偏给仪和师妹撞见了,说他擅闯见性峰,不问三七二十一,提剑就砍,差点没要了他的性命,可也真是危险。”   令狐冲心想:“我曾说过,别院中的男子若不得我号令,任谁不许上见性峰。田兄名声素来不佳,仪和师姊又是个急性子人,一见之下,自然动剑。只是田兄武功比她高得多,仪和可杀不了他。”他正想点头同意,但立即警觉:“不论她说甚么话,我赞同也好,反对也好,决不可点头或摇头。那哑婆婆决不会听到她的说话。   仪琳续道:“田伯光待得说清楚,仪和师姊已砍了十七八剑,幸好她手下留情,没真的杀了他。我一得到消息,忙赶到通元谷来,却已不见爹爹,一问旁人,都说他在院子中又哭又闹,生了好大的气,谁也不敢去跟他说话,后来就不见了。我在通元谷中四下寻找,终于在后山一个山坳里见到了他,只见他高高挂在树上。我着急得很,忙纵上树去,见他头颈中有一条绳,勒得快断气了,真是菩萨保佑,幸好及时赶到。我将他救醒了,他抱着我大哭。我见他头颈中仍是挂着那根布条,上面写的仍是‘天下第一负心薄幸’甚么的。我说:‘爹爹,这人真坏,吊了你一次,又吊你第二次。挂错了布条,他又不掉转来。“爹爹一面哭,一面说道:‘不是人家吊,是我自己上吊的。我……我不想活了。’我劝他说:‘爹爹,那人定是突然之间向你偷袭,你不小心着了他的道儿,那也不用难过。咱们找到他,叫他讲个道理出来,他如说得不对,咱们也将他吊了起来,将这条布条挂在他头颈里。’爹爹道:‘这条布条是我的,怎可挂在旁人身上?天下第一负心薄幸、好色无厌之徒,乃是我不戒和尚。哪里还有人胜得过我的?小孩儿家,就会瞎说。’哑婆婆,我听他这么说,心中可真奇了,问道:‘爹爹,这布条没挂错么?’爹爹说:‘自然没挂错。我……我对不起你娘,因此要悬树自尽,你不用管我,我真的不想活了。’”令狐冲记得不戒和尚曾对他说过,他爱上了仪琳的妈妈,只因她是个尼姑,于是为她而出家做了和尚。和尚娶尼姑,真是希奇古怪之至。他说他对不起仪琳的妈妈,想必是后来移情别恋,因此才自认是“负心薄幸、好色无厌”,想到此节,心下渐渐有些明白了。仪琳道:“我见参爹哭得伤心,也哭了起来。爹爹反而劝我,说道:‘乖孩子,别哭,别哭。爹爹倘若死了,你孤苦伶仃的在这世上,又有谁来照顾你?’他这样说,我哭得更加厉害了。”她说到这里,眼眶中泪珠莹然,神情极是凄楚,又道:“爹爹说道:‘好啦,好啦!我不死就是,只不过也太对不住你娘。’我问:‘到底你怎样对不住我娘?’爹爹叹了口气,说道:‘你娘本来是个尼姑,你是知道的了。我一见到你娘,就爱得她发狂,说甚么要娶她为妻。你娘说:“阿弥陀佛,起这种念头,也不怕菩萨嗔怪。”我说:“菩萨要怪,就只怪我一人。”你娘说:“你是俗家人,娶妻生子,理所当然。我身入空门,六根清净,再动凡心,菩萨自然要责怪了,可怎会怪到你?”我一想不错,是我决意要娶你娘,可不是你娘一心想嫁我。倘若让菩萨怪上了她,累她死后在地狱中受苦,我如何对得住她?因此我去做了和尚。菩萨自然先怪我,就算下地狱,咱们夫妻也是一块儿去。’”   令狐冲心想:“不戒大师确是个情种,为了要担负菩萨的责任,这才去做和尚,既然如此,不知后来又怎会变心?”仪琳续道:“我就问爹爹:‘后来你娶了妈妈没有?’爹爹说:‘自然娶成了,否则怎会生下你来?千不该,万不该,那日你生下来才三个月,我抱了你在门口晒太阳。’我说:‘晒太阳又有甚么不对了?’爹爹说:‘事情也真不巧,那时候有个美貌少妇,骑了马经过门口,看见我大和尚抱了个女娃娃,觉得有些奇怪,向咱们瞧了几眼,赞道:“好美的女娃娃!”我心中一乐,说道:“你也美得很啊。”那少妇向我瞪了一眼,问道:“你这女娃娃是哪里偷来的?”我说:“甚么偷不偷的?是我和尚自己生的。”那少妇忽然大发脾气,骂道:“我好好问你,你几次三番向我取笑,可不是活得不耐烦了?”我说:“取甚么笑?难道和尚不是人,就不会生孩子?你不信,我就生给你看。”哪知道那女人凶得很,从背上拔出剑来,便向我刺来,那不是太不讲道理吗?’”   令狐冲心想:“不戒大师直言无忌,说的都是真话,但听在对方耳里,却都成为无聊调笑。他既然娶妻生女,怎地又不还俗?大和尚抱了个女娃娃,原是不伦不类。”   仪琳道:“我说:‘这位太太可也太凶了。我明明是你生的,又没骗她,干么好端端地便拔剑刺人?’爹爹道:‘是啊,当时我一闪避开,说道:“你怎地不分青红皂白,便动刀剑?这女娃娃不是我生的,难道是你生的?”那女人脾气更大了,向我连刺三剑。她几剑刺我不中,出剑更快了。我当然不来怕她,就怕她伤到了你,她刺到第八剑上,我飞起一脚,将她踢了个筋斗。她站起身来,大骂我:“不要脸的恶和尚,无耻下流,调戏妇女。”“‘就在这时候,你妈妈从河边洗了衣服回来,站在旁边听着。那女人骂了几句,气愤愤的骑马走了,掉在地上的剑也不要了。我转头跟你娘说话。她一句也不答,只是哭泣。我问她为甚么事,她总是不睬。第二天早晨,你娘就不见了。桌上有一张纸,写着八个字。你猜是甚么字?那便是“负心薄幸,好色无厌”这八个字了。我抱了你到处去找她,可哪里找得到。’“我说:‘妈妈听了那女人的话,以为你真的调戏了她。’爹爹说:‘是啊,那不是冤枉吗?可是后来我想想,那也不全是冤枉,因为当时我见到那个女人,心中便想:“这女子生得好俊。”你想:我既然娶了你妈妈做老婆,心中却赞别个女人美貌,不但心中赞,口中也赞,那不是负心薄幸、好色无厌么?’”令狐冲心道:“原来仪琳师妹的妈妈醋劲儿这般厉害。当然这中间大有误会,但问个明白,不就没事了?”仪琳道:“我说:‘后来找到了妈妈没有?’爹爹说:‘我到处寻找,可哪里找得到?我想你妈是尼姑,一定去了尼姑庵中,一处处庵堂都找遍了。这一日,找到了恒山派的白云庵,你师父定逸师太见你生得可爱,心中欢喜,那时你又在生病,便叫我将你寄养在庵中,免得我带你在外奔波,送了你一条小命。’”一提到定逸师太,仪琳又不禁泫然,说道:“我从小没了妈妈,全仗师父抚养长大,可是师父给人害死了,害死她的,却是令狐大哥的师父,你瞧这可有多为难。令狐大哥跟我一样,也是自幼没了妈妈,由他师父抚养长大的。不过他比我还要苦些,不但没了妈妈,连爹爹也没有。他自然敬爱他的师父,我要是将他师父杀了,为我师父报仇,令狐大哥可不知有多伤心。我爹爹又说:他将我寄养在白云庵中之后,找遍了天下的尼姑庵,后来连蒙古、西藏、关外、西域,最偏僻的地方都找到了,始终没打听到半点我娘的音讯。想起来,我娘定是怪我爹爹调戏女人,第二天便自尽了。哑婆婆,我妈妈出家时,是在菩萨面前发过誓的,身入空门之后,决不再有情缘牵缠,可是终于拗不过爹爹,嫁了给他,刚生下我不久,便见他调戏女人,给人骂‘无耻下流’,当然生气。她是个性子十分刚烈的女子,自己以为一错再错,只好自尽了。”仪琳长长叹了口气,续道:“我爹爹说明白这件事,我才知道,为甚么他看到‘天下第一负心薄幸,好色无厌之徒’这布条时,如此伤心。我说:‘妈妈写了这张纸条骂你,你时时拿给人家看么?怎么别人竟会知道?’爹爹道:‘当然没有!我对谁也没说。这种事说了出来,好光彩吗?这中间有鬼,定是你妈妈的鬼魂找上了我,她要寻我报仇,恨我玷污了她清白,却又去调戏旁的女子。否则挂在我身上的布条,旁的字不写,怎么偏偏就写上这八个字?我知道她是在向我索命,很好,我就跟她去就是了。’“爹爹又道:‘反正我到处找你妈妈不到,到阴世去和她相会,那也正是求之不得。可惜我身子太重,上吊了片刻,绳子便断了,第二次再上吊,绳子又断了。我想拿刀抹脖子,那刀子明明在身边的,忽然又找不到了,真是想死也不容易。’我说:‘爹爹,你弄错啦,菩萨保佑,叫你不可自尽,因此绳子会断,刀子会不见。否则等我找到时,你早已死啦。’爹爹说:‘那也不错,多半菩萨罚我在世上还得多受些苦楚,不让我立时去阴世和你妈妈相见。’我说:‘先前我还道是田伯光的布条跟你掉错了,因此你生这么大的气。’爹爹说:‘怎么会掉错?不可不戒以前对你无礼,岂不是“胆大妄为”?我叫他去做媒,要令狐冲这小子来娶你,他推三阻四,总是办不成,那还不是“办事不力”?这八字评语挂在他身上,真是再合式也没有了。’我说:‘爹爹,你再叫田伯光去干这等无聊之事,我可要生气了。令狐大哥先前喜欢的是他小师妹,后来喜欢了魔教的任大小姐。他虽然待我很好,但从来就没将我放在心上。’”令狐冲听仪琳这么说,心下颇觉歉然。她对自己一片痴心,初时还不觉得,后来却渐渐明白了,但自己确然如她所说,先是喜欢岳家小师妹,后来将一腔情意转到了盈盈身上。这些时候来亡命江湖,少有想到仪琳的时刻。仪琳道:“爹爹听我这么说,忽然生起气来,大骂令狐大哥,说道:‘令狐冲这小子,有眼无珠,当真连不可不戒也不如。不可不戒还知道我女儿美貌,令狐冲却是天下第一大笨蛋。’他骂了许多粗话,难听得很,我也学不上来。他说:‘天下第一大瞎子是谁?不是左冷禅,而是令狐冲。左冷禅眼睛虽然给人刺瞎了,令狐冲可比他瞎得更厉害。’哑婆婆,爹爹这样说是很不对的,他怎么可以这样骂令狐大哥?我说:‘爹爹,岳姑娘和任大小姐都比女儿美貌百倍,孩儿怎么及得上人家?再说,孩儿已经身入空门,只是感激令狐大哥舍命相救的恩德,以及他对我师父的好处,孩儿才时时念着他。我妈妈说得对,皈依佛门之后,便当六根清净,再受情缘牵缠,菩萨是要责怪的。’“爹爹说:‘身入空门,为甚么就不可以嫁人?如果天下的女人都身入空门,再不嫁人生儿子,世界上的人都没有了。你娘是尼姑,她可不是嫁了给我,又生下你来吗?’我说:‘爹爹,咱们别说这件事了,我……我宁可当年妈妈没生下我这个人来。’”她说到这里,声音又有些哽咽,过了一会,才道:“爹爹说,他一定要去找令狐大哥,叫他娶我。我急了,对他说,要是他对令狐大哥提这等话,我永远不跟他说一句话,他到见性峰来,我也决不见他。田伯光要是向令狐大哥提这等无聊言语,我要跟仪清、仪和师姊她们说,永远不许他踏上恒山半步。爹爹知道我说得出做得到,呆了半晌,叹了一口气,一个人走了。哑婆婆,爹爹这么一去,不知甚么时候再来看我?又不知他会不会再自杀?真叫人挂念得紧。后来我找到田伯光,叫他跟着爹爹,好好照料他,说完之后,看到有许多人偷偷摸摸的走到通元谷外,躲在草丛之中,不知干甚么。我悄悄跟着过去瞧瞧,却见到了你。哑婆婆,你不会武功,又听不见人家说话,躲在那里,倘若给人家见到了,那是很危险的,以后可千万别再跟着人家去躲在草丛里了。你还道是捉迷藏吗?”令狐冲险些笑了出来,心想:“这个小师妹孩子气得很,只当人家也是孩子。”仪琳道:“这些日子中,仪和、仪清两位师姊总是督着我练剑。秦绢小师妹跟我说,她曾听到仪和、仪清她们好几位大师姊商议。大家说,令狐大哥将来一定不肯做恒山派掌门。岳不群是我们的杀师大仇,我们自然不能并入五岳派,奉他为我们掌门,因此大家叫我做掌门人。哑婆婆,我可半点也不相信。但秦师妹赌咒发誓,说一点也不假。她说,几位大师姊都说,恒山派仪字辈的群尼之中,令狐大哥对我最好,如果由我做掌门,定然最合令狐大哥的心意。她们所以决定推举我,全是为了令狐大哥。她们盼我练好剑术,杀了岳不群,那时做恒山派掌门,谁也没异议了。她这样解释,我才信了。不过这恒山派的掌门,我怎么做得来?我的剑法再练十年,也及不上仪和、仪清师姊她们,要杀岳不群,那是更加办不到了。我本来心中已乱,想到这件事,心下更加乱了。哑婆婆,你瞧我怎么办才是?”令狐冲这才恍然:“她们如此日以继夜的督促仪琳练剑,原来是盼她日后继我之位,接任恒山派掌门,委实用心良苦,可也是对我的一番厚意。”   仪琳幽幽的道:“哑婆婆,我常跟你说,我日里想着令狐大哥,夜里想着令狐大哥,做梦也总是做着他。我想到他为了救我,全不顾自己性命;想到他受伤之后,我抱了他奔逃;想到他跟我说笑,要我说故事给他听;想到在衡山县那个甚么群玉院中,我……我……跟他睡在一张床上,盖了同一条被子。哑婆婆,我明知你听不见,因此跟你说这些话也不害臊。我要是不说,整天憋在心里,可真要发疯了。我跟你说一会话,轻轻叫着令狐大哥的名字,心里就有几天舒服。”她顿了一顿,轻轻叫道:“令狐大哥,令狐大哥!”这两声叫唤情致缠绵,当真是蕴藏刻骨相思之意,令狐冲不由得身子一震。他早知道这小师妹对自己极好,却想不到她小小心灵中包藏着的深情,竟如此惊心动魄,心道:“她待我这等情意,令狐冲今生如何报答得来?”   仪琳轻轻叹息,说道:“哑婆婆,爹爹不明白我,仪和、仪清师姊她们也不明白我。我想念令狐大哥,只是忘不了他,我明知道这是不应该的。我是身入空门的女尼,怎可对一个男人念念不忘的日思夜想,何况他还是本门的掌门人?我日日求观音菩萨救我,请菩萨保佑我忘了令狐大哥。今儿早晨念经,念着救苦救难观世音菩萨的名字,我心中又在求菩萨,请菩萨保佑令狐大哥无灾无难,逢凶化吉,保佑他和任家大小姐结成美满良缘,白头偕老,一生一世都快快活活。我忽然想,为甚么我求菩萨这样,求菩萨那样,菩萨听着也该烦了。从今而后,我只求菩萨保佑令狐大哥一世快乐逍遥。他最喜欢快乐逍遥,无拘无束,但盼任大小姐将来不要管着他才好。”她出了一会神,轻声念道:“南无救苦救难观世音菩萨,南无救苦救难观世音菩萨。”   她念了十几声,抬头望了望月亮,道:“我得回去了,你也回去罢。”从怀中取出两个馒头,塞在令狐冲手中,道:“哑婆婆,今天为甚么你不瞧我,你不舒服么?”待了一会,见令狐冲不答,自言自语:“你又听不见,我却偏要问你,可真是傻了。”慢慢转身去了。令狐冲坐在石上,瞧着她的背影隐没在黑暗之中,她适才所说的那番话,一句句在心中流过,想到回肠荡气之处,当真难以自己,一时不由得痴了。也不知坐了多少时候,无意中向溪水望了一眼,不觉吃了一惊,只见水中两个倒影并肩坐在石上。他只道眼花,又道是水波晃动之故,定睛一看,明明是两个倒影。霎时间背上出了一阵冷汗,全身僵了,又怎敢回头?   从溪水中的影子看来,那人在身后不过二尺,只须一出手立时便制了自己死命,但他竟吓得呆了,不知向前纵出。这人无声无息来到身后,自己全无知觉,武功之高,难以想像,登时便起了个念头:“鬼!”想到是鬼,心头更涌起一股凉意,呆了半晌,才又向溪水中瞧去。溪水流动,那月下倒影朦朦胧胧的看不清楚,但见两个影子一模一样,都是穿着宽襟大袖的女子衣衫,头上梳髻,也是殊无分别,竟然便是自己的化身。令狐冲更加惊骇惶怖,似乎吓得连心也停止了跳动,突然之间,也不知从哪里来的一股勇气,猛地里转过头来,和那“鬼魅”面面相对。这一看清楚,不禁倒抽了一口凉气,眼见这人是个中年女子,认得便是悬空寺中那个又聋又哑的仆妇,但她如何来到身后,自己浑不觉察,实在奇怪之极。他惧意大消,讶异之情却丝毫不减,说道:“哑婆婆,原来……原来是你,这可……这可吓了我一大跳。”但听得自己的声音发颤,又甚是嘶哑。只见那哑婆婆头髻上横插一根荆钗,穿一件淡灰色布衫,竟和自己打扮全然相同。他定了定神,强笑道:“你别见怪。任大小姐记性真好,记得你穿戴的模样,给我这一乔装改扮,便和你是双胞姊妹一般了。”   他见哑婆婆神色木然,既无怒意,亦无喜色,不知心中在想些甚么,寻思:“这人古怪得紧,我扮成她的模样,给她看见了,这地方不宜多耽。”当即站起身来,向哑婆婆一揖,说道:“夜深了,就此别过。”转身向来路走去。只走出七八步,突见迎面站着一人,拦住了去路,便是那个哑婆婆,却不知她使甚么身法,这等无影无踪、无声无息的闪了过来。东方不败在对敌时身形犹如电闪,快速无伦,但总尚有形迹可寻,这个婆婆却便如是突然间从地下涌出来一般。她身法虽不及东方不败的迅捷,但如此无声无息,实不似活人。令狐冲大骇之下,知道今晚是遇到了高人,自己甚么人都不扮,偏偏扮成了她的模样,的确不免惹她生气,当下又深深一揖,说道:“婆婆,在下多有冒犯,这就去改了装束,再来悬空寺谢罪。”那哑婆婆仍是神色木然,不露丝毫喜怒之色。令狐冲道:“啊,是了!你听不到我说话。”俯身伸指,在地上写道:“对不起,以后不敢。”站起身来,见她仍然呆呆站立,对地下的字半眼也不瞧。令狐冲指着地下大字,大声道:“对不起,以后不敢!”那婆婆一动也不动。令狐冲连连作揖,比划手势,作解衣除发之状,又抱拳示歉,那婆婆始终纹丝不动。令狐冲无计可施,搔了搔头皮,道:“你不懂,我可没法子了。”侧过身子,从那婆婆身畔绕过。他左足一动,那婆婆身子微晃,已挡在他身前。令狐冲暗吸一口气,说道:“得罪!”向右跨了一步,突然间飞身而起,向左侧窜了出去。左足刚落地,那婆婆已挡在身前,拦住了去路。他连窜数次,越来越快,那婆婆竟始终挡在他面前。令狐冲急了,伸出左手向她肩头推去,那婆婆右掌疾斩而落,切向他手腕。令狐冲急忙缩手,他自知理亏,不敢和她相斗,只盼及早脱身,一低头,想从她身侧闪过,身形甫动,只觉掌风飒然,那婆婆已一掌从头顶劈到。令狐冲斜身闪让,可是这一掌来得好快,拍的一声,肩头已然中掌。那婆婆身子也是一晃,原来令狐冲体内的“吸星大法”生出反应,竟将这一掌之力吸了过去。那婆婆倏然左手伸出,两根鸡爪般又瘦又尖的指尖向他眼中插来。令狐冲大骇,忙低头避过,这一来,背心登时露出了老大破绽,幸好那婆婆也怕了他的“吸星大法”,竟不敢乘隙击下,右手一弯,向上勾起,仍是挖他眼珠。显然她打定主意,专门攻击他眼珠,不论他的“吸星大法”如何厉害,手指入眼,总是非瞎不可,柔软的眼珠也决不会吸取旁人功力。令狐冲伸臂挡格,那婆婆回转手掌,五指成抓,抓向他左眼。令狐冲忙伸左手去格,那婆婆右手飞指已抓向他的右耳。这几下兔起鹘落,势道快极,每一招都是古里古怪,似是乡下泼妇与人打架一般,可是既阴毒又快捷,数招之间,已逼得令狐冲连连倒退。那婆婆的武功其实也不甚高,所长者只是行走无声,偷袭快捷,真实功夫固然远不及岳不群、左冷禅,连盈盈也比她高明得多。但令狐冲拳脚功夫甚差,若不是那婆婆防着他的“吸星大法”,不敢和他手脚相碰,令狐冲早已接连中掌了。又拆数招,令狐冲知道若不出剑,今晚已难以脱身,当即伸手入怀去拔短剑。他右手刚碰到剑柄,那婆婆出招快如闪电,连攻了七八招,令狐冲左挡右格,更没余暇拔剑。那婆婆出招越来越毒辣,明明无怨无仇,却显是硬要将他眼珠挖了出来。令狐冲大喝一声,左掌遮住了自己双眼,右手再度入怀拔剑,拚着给她打上一掌,踢上一脚,便可拔出短剑。便在此时,头上一紧,头发已给抓住,跟着双足离地,随即天旋地转,身子在半空中迅速转动,原来那婆婆抓着他头发,将他甩得身子平飞,急转圈子,越来越快。令狐冲大叫:“喂,喂,你干甚么?”伸手乱抓乱打,想去拿她手臂,突然左右腋下一麻,已给她点中了穴道,跟着后心、后腰、前胸、头颈几处穴道中都给她点中了,全身麻软,再也动弹不得。那婆婆兀自不肯停手,将他身子不绝旋转,令狐冲只觉耳际呼呼风响,心想:“我一生遇到过无数奇事,但像此刻这般倒霉,变成了一个大陀螺给人玩弄,却也从所未有。”   那婆婆直转得他满天星斗,几欲昏晕,这才停手,拍的一声,将他重重摔在地下。   令狐冲本来自知理亏,对那婆婆并无敌意,但这时给她弄得半死不活,自是大怒,骂道:“臭婆娘当真不知好歹,我倘若一上来就拔剑,早在你身上截了几个透明窟窿。”   那婆婆冷冷的瞧着他,脸上仍是木然,全无喜怒之色。令狐冲心道:“打是打不来了,若不骂个爽快,未免太也吃亏。但此刻给她制住,如果她知我在骂人,自然有苦头给我吃。”当即想到了一个主意,笑嘻嘻地骂道:“贼婆娘,臭婆娘,老天爷知道你心地坏,因此将你造得天聋地哑,既不会笑,又不会哭,像白痴一样,便是做猪做狗,也胜过如你这般。”他越骂越恶毒,脸上也就越是笑得欢畅。他本来只是假笑,好让那婆婆不疑心自己是在骂她,但骂到后来,见那婆婆全无反应,此计已售,不由得大为得意,真的哈哈大笑起来。那婆婆慢慢走到他身边,一把抓住他头发,着地拖去。她渐行渐快,令狐冲穴道被点,知觉不失,身子在地下碰撞磨擦,好不疼痛,口中叫骂不停,要笑却是笑不出来了。那婆婆拖着他直往山上行去,令狐冲侧头察看地形,见她转而向西,竟是往悬空寺而去。令狐冲这时早已知道,不戒和尚、田伯光、漠北双熊、仇松年等人着了道儿,多半都是她做的手脚,要神不知、鬼不觉的突然将人擒住,除了她如此古怪的身手,旁人也真难以做到,只是自己曾来过悬空寺,见了这聋哑婆婆竟一无所觉,可说极笨。连方证大师、冲虚道长、盈盈、上官云这等大行家,见了她也不起疑,这哑婆婆的掩饰功夫实在做得极好。转念又想:“这婆婆如也将我高高挂在通元谷的公孙树上,又在我身上挂一块布条,说我是天下第一大淫棍之类,我身为恒山派掌门,又穿着这样一身不伦不类的女人装束,这个脸可丢得大了。幸好她是拖我去悬空寺,让她在寺中吊打一顿,不致公然出丑,也就罢了。”想到今晚虽然倒霉,但不致在恒山别院中高挂示众,倒也算是不幸中的大幸,又想:“不知她是否知晓我的身份,莫非瞧在我恒山掌门的份上,这才优待三分?”一路之上,山石将他撞得全身皮肉之伤不计其数,好在脸孔向上,还没伤到五官。到得悬空寺,那婆婆将他直向飞阁上拖去,直拖上左首灵龟阁的最高层。令狐冲叫声:“啊哟,不好!”灵龟阁外是座飞桥,下临万丈深渊,那婆婆只怕要将自己挂在飞桥之上。这悬空寺人迹罕至,十天半月中难得有人到来,这婆婆若是将自己挂在那里,不免活生生的饿死,这滋味可大大不妙了。那婆婆将他在阁中一放,径自下阁去了。令狐冲躺在地下,推想这恶婆娘到底是甚么来头,竟无半点头绪,料想必是恒山派的一位前辈名手,便如是于嫂一般的人物,说不定当年是服侍定静、定闲等人之师父的。想到此处,心下略宽:“我既是恒山掌门,她总有些香火之情,不会对我太过为难。”但转念又想:“我扮成了这副模样,只怕她认我不出。倘若她以为我也是张夫人之类,故意扮成了她的样子,前来卧底,意图不利于恒山,不免对我‘另眼相看’,多给我些苦头吃,那可糟得很了。”也不听见楼梯上脚步响声,那婆婆又已上来,手中拿了绳索,将令狐冲手脚反缚了,又从怀中取出一根黄布条子,挂在他颈中。令狐冲好奇心大起,要想看看那布条上写些甚么,可是便在此时,双眼一黑,已给她用黑布蒙住了双眼。令狐冲心想:“这婆婆好生机灵,明知我急欲看那布条,却不让看。”又想:“令狐冲是无行浪子,天下知名,这布条上自不会有甚么好话,不用看也知道。”   只觉手腕脚踝上一紧,身子腾空而起,已给高高悬挂在横梁之上。令狐冲怒气冲天,又大骂起来,他虽爱胡闹,却也心细,寻思:“我一味乱骂,毕竟难以脱身,须当慢慢运气,打通穴道,待得一剑在手,便可将她也制住了。我也将她高高挂起,再在她头颈中挂一根黄布条子,那布条上写甚么字好?天下第一大恶婆!不好,称她天下第一,说不定她心中反而喜欢,我写‘天下第十八恶婆’,让她想破了脑袋也猜不出,排名在她之上的那十七个恶婆究竟是些甚么人。”侧耳倾听,不闻呼吸之声,这婆婆已下阁去了。   挂了两个时辰,令狐冲已饿得肚中咕咕作声,但运气之下,穴道渐通,心下正自暗喜,忽然间身子一晃,砰的一声,重重摔在楼板之上,竟是那婆婆放松了绳索。但她何时重来,自己浑没半点知觉。那婆婆扯开了蒙住他眼上的黑布,令狐冲颈中穴道未通,无法低头看那布条,只见到最底下一字是个“娘”字。他暗叫“不好!”心想她写了这个“娘”字,定然当我是个女人,她写我是淫徒、浪子,都没甚么,将我当作女子,那可大大的糟糕。只见那婆婆从桌上取过一只碗来,心想:“她给我水喝,还是喝汤?最好是喝酒!”突然间头上一阵滚热,大叫一声:“啊哟!”这碗中盛的竟是热水,照头淋在他头顶。令狐冲大骂:“贼婆娘,你干甚么?”只见她从怀中取出一柄剃刀,令狐冲吃了一惊,但听得嗤嗤声响,头皮微痛,那婆婆竟在给他刹头。令狐冲又惊又怒,不知这疯婆子是何用意,过不多时,一头头发已给剃得干干净净,心想:“好啊,令狐冲今日做了和尚。啊哟,不对,我身穿女装,那是做了尼姑。”突然间心中一寒:“盈盈本来开玩笑,说叫我扮作尼姑,这一语成谶,只怕大事不妙。说不定这恶婆娘已知我是何人,认为大男人做恒山派掌门大大不妥,不但剃了我头,还要……还要将我阉了,便似不可不戒一般,教我无法秽乱佛门清净之地。这女人忠于恒山派,发起疯来,甚么事都做得出。啊哟,令狐冲今日要遭大劫,‘武林称雄,引刀自宫’,可别去练辟邪剑法。”那婆婆剃完了头,将地下的头发扫得干干净净。令狐冲心想事势紧急,疾运内力,猛冲被封的穴道,正觉被封的几处穴道有些松动,忽然背心、后腰、肩头几处穴道一麻,又给她补了几指。令狐冲长叹一声,连“恶婆娘”三字也不想骂了。   那婆婆取下他颈中的布条,放在一旁,令狐冲这才看见,布条上写道:“天下第一大瞎子,不男不女恶婆娘。”他登时暗暗叫苦:“原来这婆娘装聋作哑,她是听得见说话的,否则不戒大师说我是天下第一大瞎子,她又怎会知道?若不是不戒大师跟女儿说话时她在旁偷听,便是仪琳跟我说话之时,她在旁偷听,说不定两次她都偷听了。”当即大声道:“不用假扮了,你不是聋子。”但那婆娘仍是不理,径自伸手来解他衣衫。令狐冲大惊,叫道:“你干甚么?”嗤的一声响,那婆婆将他身上女服撕成两半,扯了下来。   令狐冲惊叫:“你要是伤了我一根毫毛,我将你斩成肉酱。”转念一想:“她将我满头头发都剃了,岂只伤我毫毛而已?”那婆婆取过一块小小磨刀石,醮了些水,将那剃刀磨了又磨,伸指一试,觉得满意了,放在一旁,从怀中取出一个瓷瓶,瓶上写着“天香断续胶”五字。令狐冲数度受伤,都曾用过恒山派的治伤灵药,一见到这瓷瓶,不用看瓶上的字,也知是此伤药,另有一种“白云熊胆丸”,用以内服。果然那婆婆跟着又从怀中取出一个瓷瓶,赫然便是“白云熊胆丸”。那婆婆再从怀里取出了几根白布条子出来,乃是裹伤用的绷带。令狐冲旧伤已愈,别无新伤,那婆婆如此安排,摆明是要在他身上新开一两个伤口了,心下只暗暗叫苦。那婆婆安排已毕,双目凝视令狐冲,隔了一会,将他身子提起,放在板桌之上,又是神色木然的瞧着他。令狐冲身经百战,纵然身受重伤,为强敌所困,亦无所惧,此刻面对着这样一个老婆婆,却是说不出的害怕。那婆婆慢慢拿起剃刀,烛火映上剃刀,光芒闪动,令狐冲额头的冷汗一滴滴的落在衣襟之上。突然之间,他心中闪过了一个念头,更不细思,大声道:“你是不戒和尚的老婆!”那婆婆身子一震,退了一步,说道:“你——怎——么——知——道?”声音干涩,一字一顿,便如是小儿初学说话一般。令狐冲初说那句话时,脑中未曾细思,经她这么一问,才去想自己为甚么知道,冷笑一声,道:“哼,我自然知道,我早就知道了。”心下却在迅速推想:“我为甚么知道?我为甚么知道?是了,她挂在不戒大师颈中字条上写‘天下第一负心薄幸、好色无厌之徒’。这“负心薄幸、好色无厌’八字评语,除了不戒大师自己之外,世上只有他妻子方才知晓。”大声道:“你心中还是念念不忘这个负心薄幸、好色无厌之徒,否则他去上吊,为甚么你要割断他上吊的绳子?他要自刎,为甚么你要偷了他的刀子?这等负心薄幸、好色无厌之徒,让他死了,岂不干净?”那婆婆冷冷的道:“让他——死得这等——爽快,岂不——便宜了——他?”令狐冲道:“是啊,让他这十几年中心急如焚,从关外找到藏边,从漠北找到西域,到每一座尼姑庵去找你,你却躲在这里享清福,那才算没便宜了他!”那婆婆道:“他罪有——应得,他娶我为妻,为甚么——调戏女子?”令狐冲道:“谁说他调戏了?人家瞧你的女儿,他也瞧了瞧人家,又有甚么不可以?”那婆婆道:“娶了妻的,再瞧女人,不可以。”令狐冲觉得这女人无理可喻,说道:“你是嫁过人的女人,为甚么又瞧男人?”那婆婆怒道:“我几时瞧男人?胡说八道!”令狐冲道:“你现在不是正瞧着我吗?难道我不是男人?不戒和尚只不过瞧了女人几眼,你却拉过我头发,摸过我头皮。我跟你说,男女授受不亲,你只要碰一碰我身上的肌肤,便是犯了清规戒律。幸好你只碰到我头皮,没摸到我脸,否则观音菩萨一定不会饶你。”他想这女人少在外间走动,不通世务,须得吓她一吓,免得她用剃刀在自己身上乱割乱划。那婆婆道:“我斩下你的手脚脑袋,也不用碰到你身子。”令狐冲道:“要斩脑袋,只管请便。”那婆婆冷笑道:“要我杀你,可也没这般容易。现下有两条路,任你自择。一条是你快快娶仪琳为妻,别害得她伤心而死。你如摆臭架子不答应,我就阉了你,叫你做个不男不女的怪物。你不娶仪琳,也就娶不得第二个不要脸的坏女人。”她十多年来装聋作哑,久不说话,口舌已极不灵便,说了这会子话,言语才流畅了些。令狐冲道:“仪琳固然是个好姑娘,难道世上除了她之外,别的姑娘都是不要脸的坏女人?”那婆婆道:“差不多了,好也好不到哪里去。你到底答不答应,快快说来。”令狐冲道:“仪琳小师妹是我的好朋友,她如知道你如此逼我,她可要生气的。”那婆婆道:“你娶了她为妻,她欢喜得很,甚么气都消了。”令狐冲道:“她是出家人,发过誓不能嫁人的。一动凡心,菩萨便要责怪。”那婆婆道:“倘若你做了和尚,菩萨便不只怪她一人了。我给你剃头,难道是白剃的么?”令狐冲忍不住哈哈大笑,说道:“原来你给我剃光了头,是要我做和尚,以便娶小尼姑为妻。你老公从前这样干,你就叫我学他的样。”那婆婆道:“正是。”令狐冲笑道:“天下光头秃子多得很,剃光了头,并不就是和尚。”那婆婆道:“那也容易,我在你脑门上烧几个香疤便是。秃头不一定是和尚,秃头而又烧香疤,那总是和尚了。”说着便要动手。令狐冲忙道:“慢来,慢来。做和尚要人家心甘情愿,哪有强迫之理?”那婆婆道:“你不做和尚,便做太监。”   令狐冲心想:这婆婆疯疯颠颠,只怕甚么事都做得出,须要先施缓兵之计,说道:“你叫我做太监之后,忽然我回心转意了,想娶仪琳小师妹为妻,那怎么办?不是害了我二人一世吗?”那婆婆怒道:“咱们学武之人,做事爽爽快快,一言而决,又有甚么三心两意、回心转意的?和尚便和尚,太监便太监!男子汉大丈夫,怎可拖泥带水?”令狐冲笑道:“做了太监,便不是男子汉大丈夫了。”那婆婆怒道:“咱们在谈论正事,谁跟你说笑?”令狐冲心想:“仪琳小师妹温柔美貌,对我又是深情一片,但我心早已属于盈盈,岂可相负?这婆婆如此无理见逼,大丈夫宁死不屈。”说道:“婆婆,我问你,一个男子汉负心薄幸,好色无厌,好是不好?”那婆婆道:“那又何用多问?这种人比猪狗也不如,枉自为人。”令狐冲道:“是了。仪琳小师妹人既美貌,对我又好,为甚么我不娶她为妻?只因我早已与另一位姑娘有了婚姻之约。这位姑娘待我恩重如山,令狐冲就算全身皮肉都给你割烂了,我也决不负她。倘若辜负了她,岂不是变成了天下第一负心薄幸、好色无厌之徒?不戒大师这个‘天下第一’的称号,便让我令狐冲给抢过来了。”那婆婆道:“这位姑娘,便是魔教的任大小姐,那日魔教教众在这里将你围住了,便是她出手相救的,是不是?”令狐冲道:“正是,这位任大小姐你是亲眼见过的。”那婆婆道:“那容易得很,我叫任大小姐抛弃了你,算是她对你负心薄幸,不是你对她负心薄幸,也就是了。”令狐冲道:“她决不会抛弃我的。她肯为我舍了性命,我也肯为她舍了性命。我不会对她负心,她也决不会对我负心。”   那婆婆道:“只怕事到临头,也由不得她。恒山别院中臭男人多得很,随便找一个来做她丈夫就是了。”令狐冲大声怒喝:“胡说八道!”   那婆婆道:“你说我办不到吗?”走出门去,只听得隔房开门之声,那婆婆重又回进房来,手中提着一个女子,手足被缚,正便是盈盈。令狐冲大吃一惊,没料到盈盈竟也已落入这婆娘的手中,见她身上并无受伤的模样,略略宽心,叫道:“盈盈,你也来了。”盈盈微微一笑,说道:“你们的说话,我都听见啦。你说决不对我负心薄幸,我听着很是欢喜。”那婆婆喝道:“在我面前,不许说这等不要脸的话。小姑娘,你要和尚呢,还是要太监?”盈盈脸上一红,道:“你的话才真难听。”那婆婆道:“我仔细想想,要令狐冲这小子抛了你,另娶仪琳,他是决计不肯的了。”令狐冲大声喝采:“你开口说话以来,这句话最有道理。”那婆婆道:“那我老人家做做好事,就让一步,便宜了令狐冲这小子,让他娶了你们两个。他做和尚,两个都娶;做太监,一个也娶不成。只不过成亲之后,你可不许欺侮我的乖女儿,你们两头大,不分大小。你年纪大着几岁,就让仪琳叫你姊姊好了。”   令狐冲道:“我……”他只说了个“我”字,哑穴上一麻,已给她点得说不出话来。那婆婆跟着又点了盈盈的哑穴,说道:“我老人家决定了的事,不许你们罗里罗唆的打岔。让你这小和尚娶两个如花如玉的老婆,还有甚么话好说?哼,不戒这老贼秃,有甚么用?见到女儿害相思病,空自干着急,我老人家一出手就马到成功。”说着飘身出房。   令狐冲和盈盈相对苦笑,说话固不能说,连手势也不能打。令狐冲凝望着她,其时朝阳初升,日光从窗外照射进来,桌上的红烛兀自未熄,不住晃动,轻烟的影子飘过盈盈皓如白玉的脸,更增丽色。只见她眼光射向抛在地下的剃刀,转向板凳上放着的药瓶和绷带,脸上露出嘲弄之意,显然在取笑他:“好险,好险!”但立即眼光转开,低垂下来,脸上罩了一层红晕,知道这种事固然不能说,连想也不能想。   令狐冲见到她娇羞无邪,似乎是做了一件大害羞事而给自己捉到一般,不禁心中一荡,不由自禁的想:“倘若我此刻身得自由,我要过去抱她一抱,亲她一亲。”   只见她眼光慢慢转将上来,与令狐冲的眼光一触,赶快避开,粉颊上红晕本已渐消,突然间又是面红过耳。令狐冲心想:“我对盈盈当然坚贞不二。那恶婆娘逼我和仪琳小师妹成亲,为求脱身,只好暂且敷衍,待得她解了我穴道,我手中有剑,还怕她怎的?这恶婆娘拳脚功夫虽好,和左冷禅、任教主他们相比,那还差得很远。剑上功夫决计不是我敌手。她胜在轻手轻脚,来去无声,实施偷袭,教人猝不及防。若是真打,盈盈会胜她三分,不戒大师也比她强些。”他想得出神,眼光一转,只见盈盈又在瞧着自己,这一次她不再害羞,显是没再想到太监的事。见她眼光斜而向上,嘴角含笑,那是在笑自己的光头,不想太监而在笑和尚了。令狐冲哈哈大笑,可是没能笑出声来,但见盈盈笑得更加欢喜了,忽见她眼珠转了几转,露出狡狯的神色,左眼眨了一下,又眨一下。令狐冲未明她的用意,只见她左眼又是眨了两下,心想:“连眨两下,那是甚么意思?啊,是了,她在笑我要娶两个老婆。”当即左眼眨了一下,收起笑容,脸上神色甚是严肃,意思说:“只娶你一个,决无二心。”盈盈微微摇头,左眼又眨了两下,意思似是说:“娶两个就两个好了!”令狐冲又摇了摇头,左眼眨了一眨。他想将头摇得大力些,以示坚决,只是周身穴道被点得太多,难以出力,脸上神气,却是诚挚之极。盈盈微微点头,眼光又转到剃刀上去,再缓缓摇了摇头。令狐冲双目凝视着她。盈盈的眼光慢慢移动,和他相对。两人相隔丈许,四目交视,忽然间心意相通,实已不必再说一句话,反正于对方的情意全然明白。娶不娶仪琳无关紧要,是和尚是太监无关紧要。两人死也好,活也好,既已有了两心如一的此刻,便已心满意足,眼前这一刻便是天长地久,纵然天崩地裂,这一刻也已拿不去、销不掉了。两人脉脉相对,也不知过了多少时候,忽听得楼梯上脚步声响,有人走上阁来,两人这才从情意缠绵、销魂无限之境中醒了过来。只听得一个少女清脆的声音道:“哑婆婆,你带我来干甚么?”正是仪琳的声音。听得她走进隔房,坐了下来,那婆婆显然陪着她在一起,但听不到她丝毫行动之声。过了一会,听得那婆婆慢慢的道:“你别叫我哑婆婆,我不是哑的。”仪琳一声尖叫,极是惊讶,颤声说道:“你……你……你不……不哑了?你好了?”那婆婆道:“我从来就不是哑巴。”仪琳道:“那……那么你从前也不聋,听……听得见我……我的话?”语声中显出极大的惊恐。那婆婆道:“孩子,你怕甚么?我听得见你的说话,那可不更好么?”令狐冲听到她语气慈和亲切,在跟亲生女儿说话时,终于露出了爱怜之意。   但仪琳仍是十分惊惶,颤声道:“不,不!我要去了!”那婆婆道:“你再坐一会,我有件很要紧的事跟你说。”仪琳道:“不,我……我不要听。你骗我,我只当你都听不见,我……我才跟你说那些话,你骗我。”她语声哽咽,已是急得哭了出来。那婆婆轻拍她的肩膀,柔声道:“好孩子,别担心。我不是骗你,我怕你闷出病来,让你说了出来,心里好过些。我来到恒山,一直就扮作又聋又哑,谁也不知道,并不是故意骗你。”仪琳抽抽噎噎的哭泣。那婆婆又柔声道:“我有一件最好的事跟你说,你听了一定很欢喜的。”仪琳道:“是我爹爹的事吗?”那婆婆道:“你爹爹,哼,我才不管他呢,是你令狐大哥的事。”仪琳颤声道:“你别提……别提他,我……我永远不跟你提他了。我要去念经啦!”那婆婆道:“不,你耽一会,听我说完。你令狐大哥跟我说,他心里其实爱你得紧,比爱那个魔教任大小姐,还要胜过十倍。”令狐冲向盈盈瞧了一眼,心下暗骂:“臭婆娘,撒这漫天大谎!”仪琳叹了口气,轻声道:“你不用哄我。我初识得他时,令狐大哥只爱他小师妹一人,爱得要命,心里便只一个小师妹。后来他小师妹对他不起,嫁了别人,他就只爱任大小姐一人,也是爱得要命,心里便只一个任大小姐。”令狐冲和盈盈目光相接,心头均是甜蜜无限。那婆婆道:“其实他一直在偷偷喜欢你,只不过你是出家人,他又是恒山派掌门,不能露出这个意思来。现下他下了大决心,许下大愿心,决意要娶你,因此先落发做了和尚。”仪琳又是一声惊呼,道:“不……不……不会的,不可以的,不能够!你……你叫他别做和尚。”那婆婆叹道:“来不及啦,他已经做了和尚。他说,不管怎么,一定要娶你为妻。倘若娶不成,他就自尽,要不然就去做太监。”   仪琳道:“做太监?我师父曾说,这是粗话,我们出家人不能说的。”那婆婆道:“太监也不是粗话,那是服侍皇帝、皇后的低三下四之人。”仪琳道:“令狐大哥最是心高气傲,不愿受人拘束,他怎肯去服侍皇帝、皇后?我看他连皇帝也不愿做,别说去服侍皇帝了。他当然不会做太监。”那婆婆道:“做太监也不是真的去服侍皇帝、皇后,那只是个比喻。做太监之人,是不会生养儿女的。”仪琳道:“我可不信。令狐大哥日后和任大小姐成亲,自然会生好几个小宝宝。他二人都这么好看,生下来的儿女,一定可爱得很。”   令狐冲斜眼相视,但见盈盈双颊晕红,娇羞中喜悦不胜。那婆婆生气了,大声道:“我说他不会生儿子,就是不会生。别说生儿子,娶老婆也不能。他发了毒誓,非娶你不可。”仪琳道:“我知道他心中只有任大小姐一个。”   那婆婆道:“他任大小姐也娶,你也娶。懂了吗?一共娶两个老婆。这世上的男人三妻四妾都有,别说娶两个了。”仪琳道:“不会的。一个人心中爱了甚么人,他就只想到这个人,朝也想,晚也想,吃饭时候、睡觉时候也想,怎能够又去想第二个人?好像我爹爹那样,自从我妈走了之后,他走遍天涯海角,到处去寻她。天下女子多得很,如果可以娶两个女人,我爹爹怎地又不另娶一个?”那婆婆默然良久,叹道:“他……他从前做错了事,后来心中懊悔,也是有的。”   仪琳道:“我要去啦。婆婆,你要是向旁人提到令狐大哥他……他要娶我甚么的,我可不能活了。”那婆婆道:“那又为甚么?他说非娶你不可,你难道不喜欢么?”仪琳道:“不,不!我时时想着他,时时向菩萨求告,要菩萨保佑他逍遥快活,只盼他无灾无难,得如心中所愿,和任大小姐成亲。婆婆,我只是盼他心中欢喜。我从来没盼望他来娶我。”那婆婆道:“他倘若娶不成你,他就决不会快活,连做人也没有乐趣了。”仪琳道:“都是我不好,只道你听不见,向你说了这许多令狐大哥的话。他是当世的大英雄,大豪杰,我只是个甚么也不懂,甚么也不会的小尼姑。他说过的,‘一见尼姑,逢赌必输’,见了我都会倒霉,怎会娶我?我皈依佛门,该当心如止水,再也不能想这种事。婆婆,你以后提也别提,我……我以后也决不见你了。”那婆婆急了,道:“你这小丫头莫名其妙。令狐冲已为你做了和尚,他说非娶你不可,倘若菩萨责怪,那就只责怪他。”仪琳轻轻叹了口气,道:“他和我爹爹也一般想么?一定不会的。我妈妈聪明美丽,性子和顺,待人再好不过,是天下最好的女人。我爹爹为她做和尚,那是应该的,我……我可连妈妈的半分儿也及不上。”   令狐冲心下暗笑:“你这个妈妈,聪明美丽固然不见得,性子和顺更是不必谈起。和你自己相比,你妈妈才半分儿不及你呢。”那婆婆道:“你怎知道?”仪琳道:“我爹爹每次见我,总是说妈妈的好处,说她温柔斯文,从来不骂人,不发脾气,一生之中,连蚂蚁也没踏死过一只。天下所有最好的女人加在一起,也及不上我妈妈。”那婆婆道:“他……他真的这样说?只怕是……是假的。”说这两句话时声音微颤,显是心中颇为激动。仪琳道:“当然是真的。我是他女儿,爹爹怎么会骗我?”霎时之间,灵龟阁中寂静无声,那婆婆似是陷入了沉思之中。仪琳道:“哑婆婆,我去了。我今后再也不见令狐大哥啦,我只是每天求观世音菩萨保佑他。”只听得脚步声响,她轻轻的走下楼去。过了良久良久,那婆婆似乎从睡梦中醒来,低低的自言自语:“他说我是天下最好的女人?他走遍天涯海角,到处在找我?那么,他其实并不是负心薄幸、好色无厌之徒?”突然间提高嗓子,叫道:“仪琳,仪琳,你在哪里?”但仪琳早已去得远了。那婆婆又叫了两声,不闻应声,急速抢下楼去。她赶得十分急促,但脚步声仍是细微如猫,几不可闻。 ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDEntityDefines.h ================================================ // // STDEntityDefines.h // STKitDemo // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #ifndef STKitDemo_STDEntityDefines_h #define STKitDemo_STDEntityDefines_h typedef enum { STDMessageTypeText, STDMessageTypeImage, STDMessageTypeSound, } STDMessageType; #endif ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDImage.h ================================================ // // STDImage.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @interface STDImage : NSManagedObject @property (nonatomic) float height; @property (nonatomic, retain) NSString * imageId; @property (nonatomic, retain) NSString * imageURL; @property (nonatomic) float width; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDImage.m ================================================ // // STDImage.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDImage.h" @implementation STDImage @dynamic height; @dynamic imageId; @dynamic imageURL; @dynamic width; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDMessage.h ================================================ // // STDMessage.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @class STDImage, STDUser; @interface STDMessage : NSManagedObject @property (nonatomic, retain) NSString * chatViewRect; @property (nonatomic, retain) NSString * content; @property (nonatomic) float height; @property (nonatomic, retain) NSString * identifier; @property (nonatomic, retain) NSString * mid; @property (nonatomic) int16_t type; @property (nonatomic) NSTimeInterval time; @property (nonatomic, retain) STDUser *from; @property (nonatomic, retain) STDImage *image; @property (nonatomic, retain) STDUser *target; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDMessage.m ================================================ // // STDMessage.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDMessage.h" @implementation STDMessage @dynamic chatViewRect; @dynamic content; @dynamic height; @dynamic identifier; @dynamic mid; @dynamic type; @dynamic time; @dynamic from; @dynamic image; @dynamic target; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDSession.h ================================================ // // STDSession.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @interface STDSession : NSManagedObject @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDSession.m ================================================ // // STDSession.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDSession.h" @implementation STDSession @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDUser.h ================================================ // // STDUser.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @class STDImage; @interface STDUser : NSManagedObject @property (nonatomic, retain) NSString * name; @property (nonatomic, retain) NSString * nick; @property (nonatomic, retain) NSString * uid; @property (nonatomic, retain) STDImage *avatar; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/Entity/STDUser.m ================================================ // // STDUser.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDUser.h" @implementation STDUser @dynamic name; @dynamic nick; @dynamic uid; @dynamic avatar; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDBaseChatCell.h ================================================ // // STDBaseChatCell.h // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @class STDMessage; @interface STDBaseChatCell : UITableViewCell @property(nonatomic, strong) UIImageView *avatarView; @property(nonatomic, strong) UIView *chatView; @property(nonatomic, strong) UIButton *bubbleImageView; /// This is abstract . subview must override this. default nil @property(nonatomic, assign) UIView *chatContentView; @property(nonatomic, weak) STDMessage *message; @end extern NSString *const NXChatCellTextActivityIdentifier; extern NSString *const NXChatCellTextLeftIdentifier; extern NSString *const NXChatCellTextRightIdentifier; extern NSString *const NXChatCellImageLeftIdentifier; extern NSString *const NXChatCellImageRightIdentifier; extern NSString *const NXChatCellQuoteLeftIdentifier; extern NSString *const NXChatCellQuoteRightIdentifier; ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDBaseChatCell.m ================================================ // // STDBaseChatCell.m // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDBaseChatCell.h" #import "STDMessage.h" #import @implementation STDBaseChatCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.frame = CGRectMake(0, 0, 320, 0); UIView *bkgView = UIView.new; self.backgroundView = bkgView; self.backgroundColor = [UIColor clearColor]; self.contentView.backgroundColor = [UIColor clearColor]; self.selectionStyle = UITableViewCellSelectionStyleDefault; self.selectedBackgroundView = UIView.new; self.selectedBackgroundView.backgroundColor = [UIColor clearColor]; self.multipleSelectionBackgroundView = UIView.new; self.multipleSelectionBackgroundView.backgroundColor = [UIColor clearColor]; self.chatView = [[UIView alloc] initWithFrame:CGRectZero]; if ([reuseIdentifier hasSuffix:@"right.identifier"] || [reuseIdentifier hasSuffix:@"left.identifier"]) { self.avatarView = [[UIImageView alloc] initWithFrame:CGRectZero]; CGRect avatarRect = CGRectMake(5, 2, 38, 38); if ([reuseIdentifier hasSuffix:@"right.identifier"]) { avatarRect = CGRectMake(CGRectGetWidth(self.bounds) - 43, 2, 38, 38); self.avatarView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin; [self addSubview:self.avatarView]; [self addSubview:self.chatView]; } else { [self.contentView addSubview:self.avatarView]; [self.contentView addSubview:self.chatView]; } self.avatarView.frame = avatarRect; } self.bubbleImageView = [UIButton buttonWithType:UIButtonTypeCustom]; self.bubbleImageView.frame = self.chatView.bounds; self.bubbleImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.bubbleImageView addTarget:self action:@selector(bubbleImageViewClicked:) forControlEvents:UIControlEventTouchUpInside]; [self.chatView addSubview:self.bubbleImageView]; } return self; } - (void)bubbleImageViewClicked:(id)sender { } - (void)setMessage:(STDMessage *)message { self.avatarView.image = [UIImage imageNamed:@"avatar72.png"]; CGRect chatViewRect = CGRectFromString(message.chatViewRect); if (!CGRectIsEmpty(chatViewRect)) { if ((self.width - CGRectGetMaxX(chatViewRect) > 100 )&& [message.identifier hasSuffix:@"right.identifier"]) { chatViewRect.origin.x += ABS([UIScreen mainScreen].bounds.size.width - [UIScreen mainScreen].bounds.size.height); } self.chatView.frame = chatViewRect; } _message = message; } - (void)setEditing:(BOOL)editing animated:(BOOL)animated { self.avatarView.userInteractionEnabled = !editing; self.chatView.userInteractionEnabled = !editing; [super setEditing:editing animated:animated]; } @end NSString *const NXChatCellTextActivityIdentifier = @"chat.text.activity.identifier"; NSString *const NXChatCellTextLeftIdentifier = @"chat.text.left.identifier"; NSString *const NXChatCellTextRightIdentifier = @"chat.text.right.identifier"; NSString *const NXChatCellImageLeftIdentifier = @"chat.image.left.identifier"; NSString *const NXChatCellImageRightIdentifier = @"chat.image.right.identifier"; NSString *const NXChatCellQuoteLeftIdentifier = @"chat.quote.left.identifier"; NSString *const NXChatCellQuoteRightIdentifier = @"chat.quote.right.identifier"; ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChat.h ================================================ // // STDChat.h // STKitDemo // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import typedef enum STDChatViewDirection { STDChatViewDirectionDefault = 1, STDChatViewDirectionLeft = STDChatViewDirectionDefault, STDChatViewDirectionRight = 2 } STDChatViewDirection; @class STDMessage; @interface STDChat : NSObject + (NSDictionary *)availableTypeIdentifiers; + (NSString *)identifierForMessageType:(int)messageType; + (CGRect)convertRect:(CGRect )rect0 fromDirection:(STDChatViewDirection)fromDirection toDirection:(STDChatViewDirection)toDirection; + (CGFloat)heightForMessageWithEntity:(STDMessage *)messageEntity identifier:(NSString **)identifier chatViewRect:(CGRect *)chatViewRect; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChat.m ================================================ // // STDChat.m // STKitDemo // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDChat.h" #import "STDImage.h" #import "STDMessage.h" #import "STDEntityDefines.h" #import #import "STDTextChatCell.h" #import "STDUser.h" const CGSize STDChatConstraintSize = {229, 9999999.0f}; const CGSize STDChatActivitySize = {266, 9999999.0f}; const CGFloat STDImageMaxWidth = 244; const CGFloat STDImageMinWidth = 60; const CGFloat STDImageMaxHeight = 303; const CGFloat STDImageMinHeight = 60; const CGFloat STDImageRatio = 1.8; @implementation STDChat + (const NSArray *)supportedTypeIdentifiers { const NSArray *identifiers = @[@"chat.text", @"chat.image"]; return identifiers; } + (const NSDictionary *)availableTypeIdentifiers { const NSDictionary *identifiers = @{@"0" : @"chat.text", @"1" : @"chat.image", @"2" : @"chat.sound"}; return identifiers; } + (NSString *)identifierForMessageType:(int)messageType { if ([[[self class] availableTypeIdentifiers] valueForKey:[NSString stringWithFormat:@"%d", messageType]]) { return [[[self class] availableTypeIdentifiers] valueForKey:[NSString stringWithFormat:@"%d", messageType]]; } return nil; } #pragma mark - Height Methods + (CGRect)convertRect:(CGRect)rect0 fromDirection:(STDChatViewDirection)fromDirection toDirection:(STDChatViewDirection)toDirection { if (fromDirection == toDirection) { return rect0; } CGFloat width = [UIScreen mainScreen].bounds.size.width; if (fromDirection == STDChatViewDirectionLeft) { CGFloat margin = rect0.origin.x; CGFloat sizeWidth = rect0.size.width; rect0.origin.x = width - margin - sizeWidth; return rect0; } else { CGFloat margin = width - CGRectGetMaxX(rect0); rect0.origin.x = margin; return rect0; } } + (CGFloat)heightForMessageWithEntity:(STDMessage *)message identifier:(NSString **)identifier chatViewRect:(CGRect *)chatViewRect { BOOL mine = [message.from.uid isEqualToString:@"97676901"]; STDMessageType messageType = message.type; NSString *suffix = mine ? @"right.identifier" : @"left.identifier"; NSString *ids = [[self class] identifierForMessageType:messageType]; BOOL supportId = [[[self class] supportedTypeIdentifiers] containsObject:ids]; if (!supportId) { ids = [[[self class] supportedTypeIdentifiers] objectAtIndex:0]; } NSString *idstr = [NSString stringWithFormat:@"%@.%@", ids, suffix]; if (identifier) { *identifier = idstr; } CGFloat height; CGRect rect0 = CGRectZero; CGSize textSize, imageSize; switch (messageType) { case STDMessageTypeSound: height = 30; break; case STDMessageTypeImage: imageSize = [[self class] imageSizeFromMessageObject:message]; rect0 = CGRectMake(45, 0, imageSize.width + 16, imageSize.height + 10); height = rect0.size.height; break; case STDMessageTypeText: default: /// 文本类型的高度计算。 textSize = [self chatTextSize:message.content constrainedToSize:STDChatConstraintSize]; rect0 = CGRectMake(45, 0, textSize.width, textSize.height); height = CGRectGetMaxY(rect0); break; } if (mine) { // 如果是自己发送的,则x轴对称 rect0 = [[self class] convertRect:rect0 fromDirection:STDChatViewDirectionLeft toDirection:STDChatViewDirectionRight]; } if (chatViewRect) { *chatViewRect = rect0; } return height; } + (CGSize)chatTextSize:(NSString *)text constrainedToSize:(CGSize)constrainedSize { UIFont *font = [[STThemeManager currentTheme] themeValueForKey:@"STDChatViewFont" whenContainedIn:[STDTextChatCell class]]; CGSize textSize = [text sizeWithFont:font constrainedToSize:constrainedSize paragraphStyle:nil]; if (textSize.width > constrainedSize.width) { textSize.width = constrainedSize.width; } textSize.width += 33; if (textSize.height < 30) { textSize.height = 48; } else { textSize.height = textSize.height + 28; } return textSize; } #pragma mark - ImageSizeScale + (CGSize)imageSizeFromMessageObject:(STDMessage *)message { STDImage *image = message.image; CGFloat width = image.width / 2, height = image.height / 2; if (width > STDImageMaxWidth || height > STDImageMaxHeight) { if (height >= width) { if (height <= width * STDImageRatio) { if (width > STDImageMaxWidth) { height = height * STDImageMaxWidth / width; width = STDImageMaxWidth; } } else { if (width < STDImageMinWidth) { width = STDImageMinWidth; height = (float)(STDImageRatio * width); } else if (width < STDImageMaxWidth / STDImageRatio) { height = (float)(width * STDImageRatio); } else { if (width > STDImageMaxWidth) { width = STDImageMaxWidth; } height = (float)(STDImageRatio * width); } } } else { if (width <= height * STDImageRatio) { if (width > STDImageMaxWidth) { height = height * STDImageMaxWidth / width; width = STDImageMaxWidth; } } else { if (height < STDImageMinHeight) { height = STDImageMinHeight; width = (float)(STDImageRatio * height); } else if (height < STDImageMaxWidth / STDImageRatio) { width = (float)(height * STDImageRatio); } else { if (width > STDImageMaxWidth) { width = STDImageMaxWidth; } height = (float)(width / STDImageRatio); } } } } else { if (width < STDImageMinWidth) { height = height * STDImageMinWidth / width; width = STDImageMinWidth; } if (height < STDImageMinHeight) { width = width * STDImageMinHeight / height; height = STDImageMinHeight; } if (width > STDImageMaxWidth) { width = STDImageMaxWidth; } if (height > STDImageMaxHeight) { height = STDImageMaxHeight; } } if (floor(width) <= 0 || floor(height) <= 0) { width = STDImageMaxWidth; height = STDImageMaxWidth; } return CGSizeMake(width, height); } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChatInputView.h ================================================ // // STDChatInputView.h // STKitDemo // // Created by SunJiangting on 13-12-24. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import extern CGFloat const STDChatInputViewDefaultHeight; @interface STDChatInputView : UIView @property (nonatomic, copy) NSString *text; @property (nonatomic, weak) UIView *parentView; @property (nonatomic, readonly, strong) UITextView *textView; - (instancetype)initWithSuperView:(UIView *)superView; @property (nonatomic, readonly, strong) UIButton *pickButton; @property (nonatomic, readonly, strong) UIButton *sendButton; - (NSString *) text; - (void) sizeToFit; @end extern NSString *const STDChatInputViewDidChangeNotification; extern NSString *const STDChatInputViewAnimationDurationUserInfoKey; extern NSString *const STDChatInputViewKeyboardHiddenUserInfoKey; extern NSString *const STDChatInputViewFrameUserInfoKey; ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChatInputView.m ================================================ // // STDChatInputView.m // STKitDemo // // Created by SunJiangting on 13-12-24. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDChatInputView.h" #import @interface STDChatInputView () @property (nonatomic, strong) UIButton *pickButton; @property (nonatomic, strong) UIButton *sendButton; @property (nonatomic, strong) UITextView *textView; @end CGFloat const STChatInputViewDefaultHeight = 45; CGFloat const STChatInputViewHorizontalMargin = 10; CGFloat const STChatInputViewSendButtonWidth = 50; @implementation STDChatInputView - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [self.textView removeObserver:self forKeyPath:@"contentSize"]; } - (instancetype)initWithSuperView:(UIView *)superView { CGFloat originY = CGRectGetHeight(superView.bounds) - STChatInputViewDefaultHeight; self = [super initWithFrame:CGRectMake(0, originY, CGRectGetWidth(superView.bounds), STChatInputViewDefaultHeight)]; if (self) { self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; self.backgroundColor = [UIColor lightGrayColor]; self.parentView = superView; CGFloat textWidth = CGRectGetWidth(superView.bounds) - STChatInputViewHorizontalMargin * 3 - STChatInputViewSendButtonWidth; self.textView = [[UITextView alloc] initWithFrame:CGRectMake(STChatInputViewHorizontalMargin, 7, textWidth, 30)]; self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.textView.scrollsToTop = NO; self.textView.showsVerticalScrollIndicator = NO; self.textView.keyboardType = UIKeyboardTypeDefault; self.textView.returnKeyType = UIReturnKeyNext; if ([self.textView respondsToSelector:@selector(layoutManager)]) { self.textView.layoutManager.allowsNonContiguousLayout = NO; } [self addSubview:self.textView]; self.sendButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.sendButton.titleLabel.font = [[STThemeManager currentTheme] themeValueForKey:@"STInputSendButton" whenContainedIn:[self class]]; [self.sendButton setTitle:@"Send" forState:UIControlStateNormal]; self.sendButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin; [self.sendButton setBackgroundImage:[UIImage imageNamed:@"chat_input_send_normal.png"] forState:UIControlStateNormal]; [self.sendButton setBackgroundImage:[UIImage imageNamed:@"chat_input_send_highlighted.png"] forState:UIControlStateHighlighted]; self.sendButton.frame = CGRectMake(self.bounds.size.width - 60.0f,7,50,30); [self addSubview:self.sendButton]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; [self.textView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL]; } return self; } - (NSString *)text { return self.textView.text; } - (void)setText:(NSString *)text { self.textView.text = text; [self sizeToFit]; } - (void)layoutSubviews { [super layoutSubviews]; self.textView.contentInset = UIEdgeInsetsZero; } - (void)sizeToFit { CGSize size = self.textView.size; CGSize contentSize = self.textView.contentSize; if (contentSize.height < 30) { return; } BOOL changed = NO; CGFloat offset = 0; contentSize.height = MIN(70, contentSize.height); if (contentSize.height <= 70) { offset = contentSize.height - size.height; size.height = contentSize.height; changed = YES; } if (!changed) { return; } CGRect frame = self.frame; frame.origin.y -= offset; frame.size.height += offset; self.frame = frame; } - (BOOL)becomeFirstResponder { return [self.textView becomeFirstResponder]; } - (BOOL)resignFirstResponder { BOOL resignFirstResponder = [super resignFirstResponder]; return [self.textView resignFirstResponder] && resignFirstResponder; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == self.textView) { CGSize size = self.textView.size; CGSize contentSize = self.textView.contentSize; if (contentSize.height < 30) { return; } BOOL changed = NO; CGFloat offset = 0; contentSize.height = MIN(70, contentSize.height); if (contentSize.height <= 70) { offset = contentSize.height - size.height; size.height = contentSize.height; changed = YES; } if (!changed) { return; } CGRect frame = self.frame; frame.origin.y -= offset; frame.size.height += offset; self.frame = frame; NSMutableDictionary *notificationUserInfo = [NSMutableDictionary dictionaryWithCapacity:2]; [notificationUserInfo setValue:@(0.25) forKey:STDChatInputViewAnimationDurationUserInfoKey]; [notificationUserInfo setValue:@([self isFirstResponder]) forKey:STDChatInputViewKeyboardHiddenUserInfoKey]; [notificationUserInfo setValue:[NSValue valueWithCGRect:frame] forKey:STDChatInputViewFrameUserInfoKey]; [[NSNotificationCenter defaultCenter] postNotificationName:STDChatInputViewDidChangeNotification object:self userInfo:notificationUserInfo]; } } - (void)keyboardWillShow:(NSNotification *) notification { NSDictionary *userInfo = notification.userInfo; CGRect keyboardFrame = [[userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat keyboardWidth = keyboardFrame.size.width; if (UIInterfaceOrientationIsLandscape(self.parentView.viewController.interfaceOrientation)) { keyboardFrame.size.width = keyboardFrame.size.height; keyboardFrame.size.height = keyboardWidth; } CGRect rect = self.frame; rect.origin.y = CGRectGetHeight(self.parentView.frame) - CGRectGetHeight(keyboardFrame) - rect.size.height; NSTimeInterval duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; UIViewAnimationCurve animationCurve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]; UIViewAnimationOptions options = UIViewAnimationCurveEaseIn | UIViewAnimationCurveEaseOut | UIViewAnimationCurveLinear; switch (animationCurve) { case UIViewAnimationCurveEaseInOut: options = UIViewAnimationOptionCurveEaseInOut; break; case UIViewAnimationCurveEaseIn: options = UIViewAnimationOptionCurveEaseIn; break; case UIViewAnimationCurveEaseOut: options = UIViewAnimationOptionCurveEaseOut; break; case UIViewAnimationCurveLinear: options = UIViewAnimationOptionCurveLinear; break; default: options = animationCurve << 16; break; } NSMutableDictionary *notificationUserInfo = [NSMutableDictionary dictionaryWithCapacity:2]; [notificationUserInfo setValue:@(duration) forKey:STDChatInputViewAnimationDurationUserInfoKey]; [notificationUserInfo setValue:@(NO) forKey:STDChatInputViewKeyboardHiddenUserInfoKey]; [notificationUserInfo setValue:[NSValue valueWithCGRect:rect] forKey:STDChatInputViewFrameUserInfoKey]; [notificationUserInfo setValue:@(options) forKey:UIKeyboardAnimationCurveUserInfoKey]; [[NSNotificationCenter defaultCenter] postNotificationName:STDChatInputViewDidChangeNotification object:self userInfo:notificationUserInfo]; [UIView animateWithDuration:duration delay:0.0 options:options animations:^{ self.frame = rect; } completion:NULL]; } - (void)keyboardWillHide:(NSNotification *) notification { NSDictionary *userInfo = notification.userInfo; UIViewAnimationCurve animationCurve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]; UIViewAnimationOptions options = UIViewAnimationCurveEaseIn | UIViewAnimationCurveEaseOut | UIViewAnimationCurveLinear; switch (animationCurve) { case UIViewAnimationCurveEaseInOut: options = UIViewAnimationOptionCurveEaseInOut; break; case UIViewAnimationCurveEaseIn: options = UIViewAnimationOptionCurveEaseIn; break; case UIViewAnimationCurveEaseOut: options = UIViewAnimationOptionCurveEaseOut; break; case UIViewAnimationCurveLinear: options = UIViewAnimationOptionCurveLinear; break; default: options = animationCurve << 16; break; } CGRect rect = self.bounds; rect.origin.y = CGRectGetHeight(self.parentView.frame) - rect.size.height; NSTimeInterval duration = [[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; NSMutableDictionary *notificationUserInfo = [NSMutableDictionary dictionaryWithCapacity:2]; [notificationUserInfo setValue:@(duration) forKey:STDChatInputViewAnimationDurationUserInfoKey]; [notificationUserInfo setValue:@(YES) forKey:STDChatInputViewKeyboardHiddenUserInfoKey]; [notificationUserInfo setValue:[NSValue valueWithCGRect:rect] forKey:STDChatInputViewFrameUserInfoKey]; [notificationUserInfo setValue:@(options) forKey:UIKeyboardAnimationCurveUserInfoKey]; [[NSNotificationCenter defaultCenter] postNotificationName:STDChatInputViewDidChangeNotification object:self userInfo:notificationUserInfo]; [UIView animateWithDuration:duration delay:0.0 options:options animations:^{ self.frame = rect; } completion:NULL]; } @end NSString *const STDChatInputViewDidChangeNotification = @"STDChatInputViewDidChangeNotification"; NSString *const STDChatInputViewAnimationDurationUserInfoKey = @"STDChatInputViewAnimationDurationUserInfoKey"; NSString *const STDChatInputViewKeyboardHiddenUserInfoKey = @"STDChatInputViewKeyboardHiddenUserInfoKey"; NSString *const STDChatInputViewFrameUserInfoKey = @"STDChatInputViewFrameUserInfoKey"; ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChatViewController.h ================================================ // // STDChatViewController.m // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // //#import "STDTableViewController.h" #import #import extern NSString *const STDChatUserDefaultID; extern NSString *const STDChatSystemDefaultID; @interface STDChatViewController : STDTableViewController - (id)initWithPageInfo:(NSDictionary *)pageInfo; @end @interface UITableView (STScrollToBottom) - (void)scrollToBottomAnimated:(BOOL)animated; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDChatViewController.m ================================================ // // STDChatViewController.m // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDChatViewController.h" #import #import "STDChat.h" #import "STDBaseChatCell.h" #import "STDTextChatCell.h" #import "STDImageChatCell.h" #import "STDImage.h" #import "STDMessage.h" #import "STDEntityDefines.h" #import "STDUser.h" #import "STDChatInputView.h" #import "STDSettingViewController.h" @interface STDChatViewController () @property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController; @property (nonatomic, strong) NSArray *textContent; @property (nonatomic, strong) NSArray *imageContent; @property (nonatomic, strong) STDChatInputView *chatInputView; @property (nonatomic, assign) BOOL needScrollBottom; @property (nonatomic, assign) BOOL tableViewEditing; @property (nonatomic, strong) NSMutableArray *selectedManagedObjects; @end NSString *const STDChatUserDefaultID = @"97676901"; NSString *const STDChatSystemDefaultID = @"97676900"; @implementation STDChatViewController #pragma mark - UserInteraction - (instancetype) initWithStyle:(UITableViewStyle)style { return [self initWithPageInfo:nil]; } - (id) initWithPageInfo:(NSDictionary *) pageInfo { self = [super initWithStyle:UITableViewStyleGrouped]; if (self) { self.hidesBottomBarWhenPushed = YES; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"STDMessage"]; NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"time" ascending:YES]; fetchRequest.sortDescriptors = @[sortDescriptor]; self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[STDCoreDataManager chatDataManager].managedObjectContext sectionNameKeyPath:nil cacheName:nil]; [self.fetchedResultsController performFetch:nil]; self.fetchedResultsController.delegate = self; self.textContent = @[@"曲曲折折的荷塘上面,弥望的是田田的叶子。叶子出水很高,像亭亭的舞女的裙。层层的叶子中间,零星地点缀着些白花,有袅娜地开着的,有羞涩地打着朵儿的;正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。微风过处,送来缕缕清香,仿佛远处高楼上渺茫的歌声似的。这时候叶子与花也有一丝的颤动,像闪电般,霎时传过荷塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有了一道凝碧的波痕。叶子底下是脉脉的流水,遮住了,不能见一些颜色;而叶子却更见风致了。", @"道生一,一生二,二生三,三生万物。万物负阴而抱阳,冲气以为和。人之所恶,唯孤、寡、不谷,而王公以为称。故物或损之而益,或益之而损。人之所教,我亦教之。强梁者不得其死,吾将以为教父。", @"先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。", @"先天下之忧而忧,后天下之乐而乐。", @"永和九年, 岁在癸丑, 暮春之初, 会于会稽山阴之兰亭, 修禊事也。 群贤毕至, 少长咸集。 此地有崇山峻岭, 茂林修竹; 又有清流激湍, 映带左右, 引以为流觞曲水, 列坐其次。 虽无丝竹管弦之盛, 一觞一咏, 亦足以畅叙幽情。", @"只因为在人群中多看了你一眼,再也没能忘掉你的容颜,梦想着偶然能有一天再相见,从此我开始孤单地思念。想你时你在天边,想你时你在眼前,想你时你在脑海,想你时你在心田。宁愿相信我们前世有约,今生的爱情故事不会再改变。宁愿用这一生等你发现,我一直在你身边,从未走远。"]; NSMutableArray * array = [NSMutableArray arrayWithCapacity:5]; NSArray * size = @[@"440*586", @"600*923", @"580*796", @"1004*1500", @"312*400", @"640*960", @"733*734", @"1280*1024"]; for (int i = 1; i <= 8; i ++) { NSString * imageName = [NSString stringWithFormat:@"chat_image_%d.jpg", i]; NSDictionary * dictionary = @{@"imageURL":imageName, @"size":size[i - 1]}; [array addObject:dictionary]; } self.imageContent = array; self.selectedManagedObjects = [NSMutableArray arrayWithCapacity:5]; } return self; } - (STDUser *)createUserIfNotExistWithID:(NSString *) userId inManageObjectContext:(NSManagedObjectContext *) managedObjectContext { NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"STDUser"]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"uid=%@", userId]; NSArray * users = [managedObjectContext executeFetchRequest:fetchRequest error:nil]; if (users.count >= 1) { return [users objectAtIndex:0]; } STDUser * user = (STDUser *)[managedObjectContext entityClassFromString:@"STDUser" name:@"STDUser"]; user.uid = userId; return user; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"聊天模板"; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonCustomItem:STBarButtonCustomItemBack target:self action:@selector(_backViewControllerActionFired:)]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"编辑" target:self action:@selector(_rightBarButtonActionFired:)]; self.navigationItem.rightBarButtonItem.enabled = (self.fetchedResultsController.fetchedObjects.count > 0); self.st_navigationController.st_sideInteractionArea = STSideInteractiveAreaNavigationBar; self.tableView.backgroundView = nil; self.tableView.backgroundColor = [UIColor st_colorWithRGB:0xE2E4E5]; self.tableView.separatorColor = [UIColor clearColor]; [self.tableView registerClass:[STDTextChatCell class] forCellReuseIdentifier:NXChatCellTextLeftIdentifier]; [self.tableView registerClass:[STDTextChatCell class] forCellReuseIdentifier:NXChatCellTextRightIdentifier]; [self.tableView registerClass:[STDImageChatCell class] forCellReuseIdentifier:NXChatCellImageLeftIdentifier]; [self.tableView registerClass:[STDImageChatCell class] forCellReuseIdentifier:NXChatCellImageRightIdentifier]; STDChatInputView * chatInputView = [[STDChatInputView alloc] initWithSuperView:self.view]; [chatInputView.sendButton addTarget:self action:@selector(saveMessageInBackground:) forControlEvents:UIControlEventTouchUpInside]; [chatInputView sizeToFit]; [self.view addSubview:chatInputView]; self.chatInputView = chatInputView; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(chatInputViewDidChanged:) name:STDChatInputViewDidChangeNotification object:chatInputView]; UITapGestureRecognizer * tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(collectionViewTapRecognizerFired:)]; tapGestureRecognizer.delegate = self; [self.tableView addGestureRecognizer:tapGestureRecognizer]; self.tableView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), self.view.bounds.size.height - CGRectGetHeight(chatInputView.bounds)); self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.scrollDirector.refreshControl.enabled = NO; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if (self.tableView.editing) { [self.tableView setEditing:NO animated:animated]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Gesture - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { [self.chatInputView resignFirstResponder]; return NO; } - (void) collectionViewTapRecognizerFired:(id) sender { } #pragma mark - Notification - (void) chatInputViewDidChanged:(NSNotification *) notification { NSTimeInterval duration = [[notification.userInfo valueForKey:STDChatInputViewAnimationDurationUserInfoKey] doubleValue]; CGRect chatViewFrame = [[notification.userInfo valueForKey:STDChatInputViewFrameUserInfoKey] CGRectValue]; CGFloat chatOriginY = CGRectGetMinY(chatViewFrame); CGRect frame = self.tableView.frame; CGFloat collectionViewVisibleHeight = CGRectGetHeight(self.view.frame) - chatOriginY; if (collectionViewVisibleHeight < self.tableView.contentSize.height) { frame.origin.y = chatOriginY - frame.size.height; } else { frame.origin.y = 0; } [UIView animateWithDuration:duration animations:^{ self.tableView.frame = frame; }]; } - (void)saveMessageInBackground:(id) sender { NSString * text = [self.chatInputView.text st_stringByTrimingWhitespace]; self.chatInputView.text = nil; if (text.length == 0) { return; } [[STDCoreDataManager chatDataManager] performBlockInBackground:^(NSManagedObjectContext *managedObjectContext) { { STDUser *user = [self createUserIfNotExistWithID:STDChatUserDefaultID inManageObjectContext:managedObjectContext]; STDMessage *message = (STDMessage *)[managedObjectContext entityClassFromString:@"STDMessage" name:@"STDMessage"]; message.from = user; message.type = STDMessageTypeText; message.content = text; message.time = [[NSDate date] timeIntervalSince1970]; NSString *identifier; CGRect chatViewRect; CGFloat height = [STDChat heightForMessageWithEntity:message identifier:&identifier chatViewRect:&chatViewRect]; message.height = height; message.identifier = identifier; message.chatViewRect = NSStringFromCGRect(chatViewRect); } STDUser *user = [self createUserIfNotExistWithID:STDChatSystemDefaultID inManageObjectContext:managedObjectContext]; STDMessage *message = (STDMessage *)[managedObjectContext entityClassFromString:@"STDMessage" name:@"STDMessage"]; message.target = user; BOOL textType = arc4random() % 2; if (![STDSettingViewController chatReceiveImage]) { textType = YES; } if (textType) { message.type = STDMessageTypeText; int contentIdx = (arc4random() % self.textContent.count); message.content = [self.textContent objectAtIndex:contentIdx]; } else { message.type = STDMessageTypeImage; int contentIdx = (arc4random() % self.imageContent.count); NSDictionary *info = [self.imageContent objectAtIndex:contentIdx]; NSString *size = [info valueForKey:@"size"]; NSArray *sizes = [size componentsSeparatedByString:@"*"]; STDImage *image = (STDImage *)[managedObjectContext entityClassFromString:@"STDImage" name:@"STDImage"]; image.width = [sizes[0] floatValue]; image.height = [sizes[1] floatValue]; image.imageURL = [info valueForKey:@"imageURL"]; message.image = image; } message.time = [[NSDate date] timeIntervalSince1970]; NSString * identifier; CGRect chatViewRect; CGFloat height = [STDChat heightForMessageWithEntity:message identifier:&identifier chatViewRect:&chatViewRect]; message.height = height; message.identifier = identifier; message.chatViewRect = NSStringFromCGRect(chatViewRect); [[STDCoreDataManager chatDataManager] saveManagedObjectContext:managedObjectContext error:nil]; } completionHandler:NULL]; } #pragma mark - TableViewDataSource - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.fetchedResultsController.sections.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section { return [[self.fetchedResultsController.sections objectAtIndex:section] numberOfObjects]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { id managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath]; STDMessage *message = (STDMessage *) managedObject; return message.height + 5; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { STDMessage *message = [self.fetchedResultsController objectAtIndexPath:indexPath]; STDBaseChatCell *chatViewCell = [tableView dequeueReusableCellWithIdentifier:message.identifier forIndexPath:indexPath]; chatViewCell.message = message; return chatViewCell; } - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { STDMessage *message = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.selectedManagedObjects addObject:message]; [self _selectedObjectChanged]; } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { STDMessage *message = [self.fetchedResultsController objectAtIndexPath:indexPath]; [self.selectedManagedObjects removeObject:message]; [self _selectedObjectChanged]; } #pragma mark - NSFetchedResultsDelegate - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ switch (type) { case NSFetchedResultsChangeInsert: self.needScrollBottom = YES; [self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationMiddle]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop]; break; case NSFetchedResultsChangeUpdate: [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; break; case NSFetchedResultsChangeMove: [self.tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath]; break; default: break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{ switch (type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationNone]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationNone]; break; case NSFetchedResultsChangeUpdate: [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationNone]; break; default: break; } } - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller{ [self.tableView beginUpdates]; } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{ [self.tableView endUpdates]; if (self.needScrollBottom) { dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView scrollToBottomAnimated:YES]; }); } self.navigationItem.rightBarButtonItem.enabled = (self.fetchedResultsController.fetchedObjects.count > 0); self.needScrollBottom = NO; } - (void)_selectedObjectChanged { if (!self.tableView.isEditing) { return; } UIButton *rightBarButton = (UIButton *)self.navigationItem.rightBarButtonItem.customView; if (self.selectedManagedObjects.count == 0) { [rightBarButton setTitle:@"取消" forState:UIControlStateNormal]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonCustomItem:STBarButtonCustomItemBack target:self action:@selector(_backViewControllerActionFired:)]; } else { [rightBarButton setTitle:@"截取" forState:UIControlStateNormal]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"删除" target:self action:@selector(_deleteViewControllerActionFired:)]; } } - (void)_rightBarButtonActionFired:(UIButton *)rightBarButton { NSString *title = [rightBarButton titleForState:UIControlStateNormal]; if ([title isEqualToString:@"取消"]) { [self _resetNavigationItems]; if (self.tableView.isEditing) { [self.tableView setEditing:NO animated:YES]; } [rightBarButton setTitle:@"编辑" forState:UIControlStateNormal]; self.tableViewEditing = NO; } else if ([title isEqualToString:@"编辑"]) { [rightBarButton setTitle:@"取消" forState:UIControlStateNormal]; [self.tableView setEditing:YES animated:YES]; [self.selectedManagedObjects removeAllObjects]; self.tableViewEditing = NO; } else if ([title isEqualToString:@"截取"]) { if (self.tableViewEditing) { return; } [STIndicatorView showInView:self.view animated:NO]; self.tableViewEditing = YES; [self _snapshotMessageViewCellsCompletion:^{ [self.selectedManagedObjects removeAllObjects]; [self _resetNavigationItems]; [self.tableView setEditing:NO animated:YES]; [STIndicatorView hideInView:self.view animated:YES]; self.tableViewEditing = NO; }]; } } - (void)_resetNavigationItems { UIButton *rightBarButton = (UIButton *)self.navigationItem.rightBarButtonItem.customView; [rightBarButton setTitle:@"编辑" forState:UIControlStateNormal]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonCustomItem:STBarButtonCustomItemBack target:self action:@selector(_backViewControllerActionFired:)]; } - (void)_backViewControllerActionFired:(id)sender { [self.st_navigationController popViewControllerAnimated:YES]; } - (void)_deleteViewControllerActionFired:(id)sender { self.tableViewEditing = YES; [[STDCoreDataManager chatDataManager] performBlockOnMainThread:^(NSManagedObjectContext * context) { [self.selectedManagedObjects enumerateObjectsUsingBlock:^(STDMessage * obj, NSUInteger idx, BOOL *stop) { [context deleteObject:obj]; }]; [[STDCoreDataManager chatDataManager] saveManagedObjectContext:context error:nil]; } completionHandler:NULL]; [self.selectedManagedObjects removeAllObjects]; self.tableViewEditing = NO; if (self.tableView.isEditing) { [self.tableView setEditing:NO animated:YES]; } [self _resetNavigationItems]; } - (void)_snapshotMessageViewCellsCompletion:(void(^)(void))completionHandler { dispatch_async(dispatch_get_main_queue(), ^{ UIView *shotView = [[UIView alloc] initWithFrame:CGRectZero]; shotView.backgroundColor = self.tableView.backgroundColor; [self.view addSubview:shotView]; NSArray *messages = [self.selectedManagedObjects sortedArrayUsingComparator:^NSComparisonResult(STDMessage * obj1, STDMessage * obj2) { return obj1.time < obj2.time ? NSOrderedAscending:NSOrderedDescending; }]; __block CGFloat height = 0.0f; CGFloat width = CGRectGetWidth(self.tableView.frame); [messages enumerateObjectsUsingBlock:^(STDMessage * message, NSUInteger idx, BOOL *stop) { UIView * messageCell; switch (message.type) { case STDMessageTypeText: messageCell = [[STDTextChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:message.identifier]; break; case STDMessageTypeImage: messageCell = [[STDImageChatCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:message.identifier]; break; default: break; } CGFloat tempHeight = message.height + 5; if (height < tempHeight) { height = tempHeight; } messageCell.frame = CGRectMake(0, 0, width, tempHeight); [messageCell setValue:message forKey:@"message"]; [shotView addSubview:messageCell]; }]; BOOL horizontal = NO; __block CGFloat left = 0, top = 0, shotWidth = 0, shotHeight = 0; [shotView.subviews enumerateObjectsUsingBlock:^(STDBaseChatCell *subview, NSUInteger idx, BOOL *stop) { if ([subview isKindOfClass:[STDBaseChatCell class]]) { CGRect frame = subview.frame; // 如果是横向的 if (horizontal) { frame.origin.y = (height - subview.height) / 2; frame.origin.x = left; left += subview.width; shotWidth = left; shotHeight = height; } else { frame.origin.y = top; top += subview.height; shotWidth = subview.width; shotHeight = top; } subview.frame = frame; } }]; CGRect shotFrame = shotView.frame; shotFrame.size.width = shotWidth; shotFrame.size.height = shotHeight; shotView.frame = shotFrame; UIGraphicsBeginImageContextWithOptions(shotView.frame.size, false, [UIScreen mainScreen].scale); CGContextRef context = UIGraphicsGetCurrentContext(); [shotView.layer renderInContext:context]; UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //保存到相册中 __weak STDChatViewController *weakSelf = self; STImageWriteToPhotosAlbum(image, @"STKitDemo", ^(UIImage *image, NSError *error) { [weakSelf image:image didFinishSavingWithError:error contextInfo:NULL]; }); [shotView removeFromSuperview]; if (completionHandler) { completionHandler(); } }); } - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { if (!error) { STIndicatorView *indicatorView = [STIndicatorView showInView:self.view.window animated:YES]; indicatorView.blurEffectStyle = STBlurEffectStyleDark; indicatorView.indicatorType = STIndicatorTypeText; indicatorView.textLabel.text = @"保存成功"; indicatorView.cornerRadius = 1; indicatorView.textLabel.font = [UIFont systemFontOfSize:18]; indicatorView.minimumSize = CGSizeMake(130, 80); [indicatorView hideAnimated:YES afterDelay:1.5]; } } - (void) leftBarButtonItemAction:(id) sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } - (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; [self.tableView reloadData]; } @end @implementation UITableView (STScrollToBottom) - (void)scrollToBottomAnimated:(BOOL)animated { NSInteger sections = self.numberOfSections; if (sections == 0) { return; } while (![self numberOfRowsInSection:(sections - 1)] && sections >= 1) { sections --; } if (sections == 0) { return; } NSInteger rows = [self numberOfRowsInSection:(sections - 1)]; if (CGRectGetHeight(self.bounds) > self.contentSize.height) { return; } NSIndexPath * indexPath = [NSIndexPath indexPathForRow:(rows - 1) inSection:(sections - 1)]; void(^animations)(void) = ^(void) { [self scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO]; }; if (animated) { [UIView animateWithDuration:0.15 animations:animations]; } else { animations(); } } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDImageChatCell.h ================================================ // // STDImageChatCell.h // STKitDemo // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDBaseChatCell.h" @interface STDImageChatCell : STDBaseChatCell @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDImageChatCell.m ================================================ // // STDImageChatCell.m // STKitDemo // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDImageChatCell.h" #import #import "STDMessage.h" #import "STDImage.h" void trim(NSString * arg0) { } @implementation STDImageChatCell - (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // Initialization code self.chatView.frame = CGRectMake(45, 0, 20, 20); NSString * bubbleImageName; CGRect contentFrame; if ([reuseIdentifier hasSuffix:@"left.identifier"]) { bubbleImageName = @"bubble_image_white.png"; contentFrame = CGRectMake(11, 4, 4, 10); } else { bubbleImageName = @"bubble_image_green.png"; contentFrame = CGRectMake(5, 4, 4, 10); } UIImage *bubbleImage = [[UIImage imageNamed:bubbleImageName] resizableImageWithCapInsets:UIEdgeInsetsMake(30, 15, 10, 15) resizingMode:UIImageResizingModeStretch]; self.bubbleImageView.adjustsImageWhenHighlighted = NO; self.bubbleImageView.adjustsImageWhenDisabled = NO; self.bubbleImageView.userInteractionEnabled = NO; [self.bubbleImageView setBackgroundImage:bubbleImage forState:UIControlStateNormal]; STImageView *contentImageView = [[STImageView alloc] initWithFrame:contentFrame]; contentImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; contentImageView.clipsToBounds = YES; contentImageView.contentMode = UIViewContentModeScaleAspectFill; [self.chatView addSubview:contentImageView]; [self.chatView bringSubviewToFront:self.bubbleImageView]; self.chatContentView = contentImageView; } return self; } - (void)setMessage:(STDMessage *)message { [super setMessage:message]; STImageView *chatImageView = (STImageView *) self.chatContentView; chatImageView.image = [UIImage imageNamed:message.image.imageURL]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDModel.xcdatamodeld/.xccurrentversion ================================================ _XCCurrentVersionName STDModel 2.xcdatamodel ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDModel.xcdatamodeld/STDModel 2.xcdatamodel/contents ================================================ ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDModel.xcdatamodeld/STDModel.xcdatamodel/contents ================================================ ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDTextChatCell.h ================================================ // // STDTextChatCell.h // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDBaseChatCell.h" @interface STDTextChatCell : STDBaseChatCell @end ================================================ FILE: STKitDemo/Classes/Modules/Services/CoreData/STDTextChatCell.m ================================================ // // STDTextChatCell.m // STKitDemo // // Created by SunJiangting on 13-12-18. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDTextChatCell.h" #import #import "STDMessage.h" @interface STDTextChatCell () @end @implementation STDTextChatCell - (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.chatView.frame = CGRectMake(45, 0, 35, 43); NSString *bubbleImageName; CGRect contentFrame; if ([reuseIdentifier hasSuffix:@"left.identifier"]) { bubbleImageName = @"bubble_text_white.png"; contentFrame = CGRectMake(20, 10, 2, 20); } else { bubbleImageName = @"bubble_text_green.png"; contentFrame = CGRectMake(13, 10, 2, 20); } UIImage *bubbleImage = [[UIImage imageNamed:bubbleImageName] resizableImageWithCapInsets:UIEdgeInsetsMake(30, 15, 10, 15) resizingMode:UIImageResizingModeStretch]; [self.bubbleImageView setBackgroundImage:bubbleImage forState:UIControlStateNormal]; [self.bubbleImageView addTarget:self action:@selector(bubbleImageViewTouchDown:) forControlEvents:UIControlEventTouchDown]; [self.bubbleImageView addTarget:self action:@selector(bubbleImageViewTouchCancel:) forControlEvents:(UIControlEventTouchCancel | UIControlEventTouchUpInside | UIControlEventTouchUpOutside | UIControlEventTouchDragExit | UIControlEventTouchDragOutside)]; self.bubbleImageView.clipsToBounds = YES; STLinkLabel *linkLabel = [[STLinkLabel alloc] initWithFrame:contentFrame]; linkLabel.font = [[STThemeManager currentTheme] themeValueForKey:@"STDChatViewFont" whenContainedIn:[STDTextChatCell class]]; linkLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; linkLabel.backgroundColor = [UIColor clearColor]; linkLabel.delegate = self; [self.chatView addSubview:linkLabel]; self.chatContentView = linkLabel; } return self; } - (void)setMessage:(STDMessage *)message { [super setMessage:message]; UILabel *chatTextView = (UILabel *) self.chatContentView; chatTextView.text = message.content; } - (void)bubbleImageViewTouchDown:(id) sender { [self performSelector:@selector(didClickText:) withObject:sender afterDelay:0.5]; } - (void)bubbleImageViewTouchCancel:(id) sender { [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(didClickText:) object:sender]; } - (BOOL)canBecomeFirstResponder { return YES; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (![NSStringFromSelector(action) isEqualToString:@"copyMenuActionFired:"]) { return NO; } return YES; } - (void)copyMenuActionFired:(id) sender { UIPasteboard * pasteboard = [UIPasteboard generalPasteboard]; pasteboard.string = self.message.content; } - (void)didClickText:(id) sender { [self becomeFirstResponder]; UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"拷贝" action:@selector(copyMenuActionFired:)]; UIMenuController *menuController = [UIMenuController sharedMenuController]; menuController.menuItems = @[menuItem]; [menuController setTargetRect:self.bubbleImageView.frame inView:self.bubbleImageView.superview]; [menuController setMenuVisible:YES animated:YES]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[UIApplication sharedApplication].keyWindow endEditing:YES]; }); } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Recorder/SCSiriWaveformView.h ================================================ // // SCSiriWaveformView.h // SCSiriWaveformView // // Created by Stefan Ceriu on 12/04/2014. // Copyright (c) 2014 Stefan Ceriu. All rights reserved. // @interface SCSiriWaveformView : UIView /* * Tells the waveform to redraw itself using the given level (normalized value) */ -(void)updateWithLevel:(CGFloat)level; /* * The total number of waves * Default: 5 */ @property (nonatomic, assign) NSUInteger numberOfWaves; /* * Color to use when drawing the waves * Default: white */ @property (nonatomic, strong) UIColor *waveColor; /* * Line width used for the proeminent wave * Default: 3.0f */ @property (nonatomic, assign) CGFloat primaryWaveLineWidth; /* * Line width used for all secondary waves * Default: 1.0f */ @property (nonatomic, assign) CGFloat secondaryWaveLineWidth; /* * The amplitude that is used when the incoming amplitude is near zero. * Setting a value greater 0 provides a more vivid visualization. * Default: 0.01 */ @property (nonatomic, assign) CGFloat idleAmplitude; /* * The frequency of the sinus wave. The higher the value, the more sinus wave peaks you will have. * Default: 1.5 */ @property (nonatomic, assign) CGFloat frequency; /* * The current amplitude */ @property (nonatomic, assign, readonly) CGFloat amplitude; /* * The lines are joined stepwise, the more dense you draw, the more CPU power is used. * Default: 5 */ @property (nonatomic, assign) CGFloat density; /* * The phase shift that will be applied with each level setting * Change this to modify the animation speed or direction * Default: -0.15 */ @property (nonatomic, assign) CGFloat phaseShift; @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Recorder/SCSiriWaveformView.m ================================================ // // SCSiriWaveformView.m // SCSiriWaveformView // // Created by Stefan Ceriu on 12/04/2014. // Copyright (c) 2014 Stefan Ceriu. All rights reserved. // #import "SCSiriWaveformView.h" @interface SCSiriWaveformView () @property (nonatomic, assign) CGFloat phase; @property (nonatomic, assign) CGFloat amplitude; @end @implementation SCSiriWaveformView - (id)init { if(self = [super init]) { [self setup]; } return self; } - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setup]; } return self; } - (void)awakeFromNib { [self setup]; } - (void)setup { self.frequency = 1.5f; self.amplitude = 0.7f; self.idleAmplitude = 0.01f; self.numberOfWaves = 5; self.phaseShift = -0.065f; self.density = 1.5f; self.waveColor = [UIColor whiteColor]; self.primaryWaveLineWidth = 3.0f; self.secondaryWaveLineWidth = 1.0f; } -(void)updateWithLevel:(CGFloat)level { self.phase += self.phaseShift; self.amplitude = fmax( 5 * level , self.idleAmplitude); if (self.amplitude > 1) { self.amplitude = 1; } [self setNeedsDisplay]; } // Thanks to Raffael Hannemann https://github.com/raffael/SISinusWaveView - (void)drawRect:(CGRect)rect { // We draw multiple sinus waves, with equal phases but altered amplitudes, multiplied by a parable function. for(int i=0; i < self.numberOfWaves; i++) { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(context, (i==0 ? self.primaryWaveLineWidth : self.secondaryWaveLineWidth)); CGFloat halfHeight = CGRectGetHeight(self.bounds) / 2.0f; CGFloat width = CGRectGetWidth(self.bounds); CGFloat mid = width / 2.0f; const CGFloat maxAmplitude = halfHeight - 4.0f; // 4 corresponds to twice the stroke width // Progress is a value between 1.0 and -0.5, determined by the current wave idx, which is used to alter the wave's amplitude. CGFloat progress = 1.0f - (CGFloat)i / self.numberOfWaves; CGFloat normedAmplitude = (1.5f * progress - 0.5f) * self.amplitude; [[self.waveColor colorWithAlphaComponent:(progress / 3.0f * 2.0f) + (1.0f / 3.0f)] set]; for(CGFloat x = 0; x #import #import #import #import typedef NS_ENUM(NSInteger, STWaveStyle) { SWaveStyleBar, SWaveStyleCurve, SWaveStyleBezier, SWaveStyleMedia, }; /// 模拟window media player @interface STWaveBarView : UIView { GLint _backingWidth; GLint _backingHeight; GLuint _renderBuffer; GLuint _frameBuffer; EAGLContext *_context; } @property(nonatomic, assign) NSInteger channels; @property(nonatomic, assign) STWaveStyle waveStyle; - (void)appendDataWithAudioBuffer:(AudioQueueBufferRef)bufferRef; - (void)reset; - (void)setInterfaceOrientation:(UIInterfaceOrientation)orientation; @end @interface STWaveBarView (OpenGLES) @end ================================================ FILE: STKitDemo/Classes/Modules/Services/Recorder/STWaveBarView.m ================================================ // // STWaveBarView.m // STKitDemo // // Created by SunJiangting on 13-3-22. // Copyright (c) 2013年 sun. All rights reserved. // #import "STWaveBarView.h" #import @interface STWaveBarView () { CADisplayLink *_displayLink; STWaveAnalysis *_analysis; NSArray *_frequency; CFAbsoluteTime _updatedTime; CGFloat _scaleFactor; } @property (nonatomic, strong) NSMutableArray *heightArray; @end @implementation STWaveBarView + (Class)layerClass { return [CAEAGLLayer class]; } - (void) dealloc { if([EAGLContext currentContext] == _context) { [EAGLContext setCurrentContext:nil]; } [[NSNotificationCenter defaultCenter] removeObserver:self]; [_displayLink invalidate]; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.heightArray = [NSMutableArray arrayWithCapacity:_frequency.count]; _analysis = [STWaveAnalysis new]; _scaleFactor = self.contentScaleFactor = [[UIScreen mainScreen] scale]; CAEAGLLayer *eaglLayer = (CAEAGLLayer*) self.layer; eaglLayer.opaque = YES; eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking:@(GL_FALSE), kEAGLDrawablePropertyColorFormat:kEAGLColorFormatRGBA8}; _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1]; if(!_context || ![EAGLContext setCurrentContext:_context] || ![self createFramebuffer]) { return nil; } [self setupView]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appliationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; self.backgroundColor = [UIColor blackColor]; self.channels = 1; self.waveStyle = SWaveStyleMedia; } return self; } - (void)setFrame:(CGRect)frame { [super setFrame:frame]; _analysis.constraintsHeight = frame.size.height - 30; } - (void)appendDataWithAudioBuffer:(AudioQueueBufferRef) bufferRef { if (!bufferRef || bufferRef->mAudioDataByteSize < self.channels * FFT_BUFFER_SIZE) { [_displayLink invalidate]; _displayLink = nil; return; } if (!_displayLink) { _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(paintRunLoop:)]; _displayLink.frameInterval = 1; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; _updatedTime = CFAbsoluteTimeGetCurrent(); } NSData *data = [NSData dataWithBytes:bufferRef->mAudioData length:bufferRef->mAudioDataByteSize]; NSArray *heights = [_analysis heightForBarWithData:data channels:self.channels constraintsFrequency:_frequency]; [heights enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { CGFloat old = [[self.heightArray objectAtIndex:idx] floatValue]; CGFloat new = [obj floatValue]; /* Decrease the bars if needed */ [self.heightArray replaceObjectAtIndex:idx withObject:@(MAX(old, new ))]; }]; } - (void)reset { [self.heightArray removeAllObjects]; for (int i = 0; i < _frequency.count - 1; i ++) { [self.heightArray addObject:@(0.0f)]; } } - (void)drawMediaWithWaveInfo:(NSDictionary *) userInfo { if (!_frameBuffer) { return; } [EAGLContext setCurrentContext:_context]; glBindFramebufferOES(GL_FRAMEBUFFER_OES, _frameBuffer); glClear(GL_COLOR_BUFFER_BIT); glColor4f(0.0f, 1.0f, 0.0f, 0.7f); CGFloat width = CGRectGetWidth(self.bounds); CGFloat barWidth = width * 0.75 * _scaleFactor / (CGFloat)(_frequency.count - 1); CGFloat barMargin =width * 0.25 * _scaleFactor / (CGFloat)(_frequency.count - 1);; [self.heightArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { CGFloat barHeight = [obj floatValue] * _scaleFactor; CGFloat barLeft = idx * (barMargin + barWidth); CGRect frame = CGRectMake(barLeft, 0, barWidth, barHeight); GLfloat vertices[] = { CGRectGetMinX(frame), CGRectGetMinY(frame), CGRectGetMaxX(frame), CGRectGetMinY(frame), CGRectGetMaxX(frame), CGRectGetMaxY(frame), CGRectGetMinX(frame), CGRectGetMaxY(frame), }; glVertexPointer(2, GL_FLOAT, 0, vertices); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); }]; glPopMatrix(); glFlush(); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _renderBuffer); [_context presentRenderbuffer:GL_RENDERBUFFER_OES]; } - (void)paintRunLoop:(id)sender { [self drawMediaWithWaveInfo:nil]; CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent(); // 下落高度 CGFloat t = currentTime - _updatedTime; CGFloat fallHeight = 100 * t; __block CGFloat totalHeight = 0.0f; for (int i = 0; i < self.heightArray.count; i ++) { CGFloat barHeight = [[self.heightArray objectAtIndex:i] floatValue]; barHeight -= fallHeight; if (barHeight <= 0.0) { barHeight = 0.0; } [self.heightArray replaceObjectAtIndex:i withObject:@(barHeight)]; totalHeight += barHeight; } if (totalHeight <= 0.0) { [self drawMediaWithWaveInfo:nil]; [_displayLink invalidate]; _displayLink = nil; } _updatedTime = currentTime; } - (void)setInterfaceOrientation:(UIInterfaceOrientation) orientation { if (UIInterfaceOrientationIsPortrait(orientation)) { _frequency = @[@(0), @(1), @(2), @(3), @(5), @(7), @(10), @(14), @(20), @(28), @(40), @(54), @(74), @(101), @(137), @(187), @(255)]; } else { _frequency = @[@(0),@(2),@(4),@(6),@(8),@(10),@(12),@(14),@(16),@(18),@(20),@(22),@(24),@(26),@(28),@(30),@(32),@(34),@(36),@(38),@(40),@(42),@(44),@(46),@(48),@(50),@(52),@(54),@(56),@(58),@(60),@(62),@(64),@(66),@(68),@(70),@(72),@(75),@(78),@(81),@(85),@(91),@(97),@(103),@(110),@(118),@(127),@(137),@(151),@(164),@(255)]; } [self.heightArray removeAllObjects]; for (int i = 0; i < _frequency.count - 1; i ++) { [self.heightArray addObject:@(0.0f)]; } } - (BOOL)createFramebuffer { glGenFramebuffersOES(1, &_frameBuffer); glGenRenderbuffersOES(1, &_renderBuffer); glBindFramebufferOES(GL_FRAMEBUFFER_OES, _frameBuffer); glBindRenderbufferOES(GL_RENDERBUFFER_OES, _renderBuffer); [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id)self.layer]; glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _renderBuffer); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_backingWidth); glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_backingHeight); if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) { NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)); return NO; } return YES; } - (void)setupView { // Sets up matrices and transforms for OpenGL ES glViewport(0, 0, _backingWidth, _backingHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(0, _backingWidth, 0, _backingHeight, -1.0f, 1.0f); glMatrixMode(GL_MODELVIEW); glClearColor(0.0f/255. ,0.0f/255., 0.f/255., 1.0f); glEnableClientState(GL_VERTEX_ARRAY); } - (void)destroyFramebuffer { glDeleteFramebuffersOES(1, &_frameBuffer); _frameBuffer = 0; glDeleteRenderbuffersOES(1, &_renderBuffer); _renderBuffer = 0; } - (void)layoutSubviews { [EAGLContext setCurrentContext:_context]; [self destroyFramebuffer]; [self createFramebuffer]; glViewport(0, 0, _backingWidth, _backingHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(0, _backingWidth, 0, _backingHeight, -1.0f, 1.0f); } - (void)appliationWillResignActive:(id)sender { // invalidate displaylink when resign active [_displayLink invalidate]; _displayLink = nil; [self destroyFramebuffer]; } - (void)applicationDidBecomeActive:(id)sender { [self createFramebuffer]; // start the displaylink } @end ================================================ FILE: STKitDemo/Classes/Modules/Services/STDServiceViewController.h ================================================ // // STDServiceViewController.h // STKitDemo // // Created by SunJiangting on 14-3-8. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import "STDTextTableViewController.h" @interface STDServiceViewController : STDTextTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Services/STDServiceViewController.m ================================================ // // STDServiceViewController.m // STKitDemo // // Created by SunJiangting on 14-3-8. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDServiceViewController.h" #import "STDRecordViewController.h" #import "STDReaderViewController.h" #import "STARootViewController.h" #import "STDChatViewController.h" @interface STDServiceViewController () @property(nonatomic, strong) NSArray *dataSource; @end @implementation STDServiceViewController @dynamic dataSource; - (instancetype)initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:5]; STDTableViewCellItem *item00 = [[STDTableViewCellItem alloc] initWithTitle:@"在线聊天" target:self action:@selector(chatActionFired)]; STDTableViewSectionItem *section0 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"使用CoreData对聊天内容进行存储,并且封装了一些常用的气泡。PS:里面包含一个截图的功能,可以截长图哦~~" items:@[item00]]; [dataSource addObject:section0]; STDTableViewCellItem *item10 = [[STDTableViewCellItem alloc] initWithTitle:@"音频测试" target:self action:@selector(recordActionFired)]; STDTableViewSectionItem *section1 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"使用AudioQueue封装了音频的录音,播放等功能,可以用于实时通话中。并且实现了音频的可视化分析,使用OpenGLES对可视化的效果进行展示" items:@[item10]]; [dataSource addObject:section1]; STDTableViewCellItem *item20 = [[STDTableViewCellItem alloc] initWithTitle:@"算法演示" target:self action:@selector(avcActionFired)]; STDTableViewSectionItem *section2 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"由于本人算法实在太差,所以在学习算法的过程中,用了一种可视化,可理解的方式进行了学习。当然重点还是iOS方面动画序列的处理" items:@[ item20 ]]; [dataSource addObject:section2]; STDTableViewCellItem *item30 = [[STDTableViewCellItem alloc] initWithTitle:@"电子小说" target:self action:@selector(readerActionFired)]; STDTableViewSectionItem *section3 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"使用CoreText+UIPageViewController完成的一个简易电子阅读器,封装了对文字的分页(每页显示多少文字),做过电子书的你懂的。" items:@[ item30 ]]; [dataSource addObject:section3]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"常用模块"; if (self.st_sideBarController) { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.autoresizingMask = UIViewAutoresizingFlexibleHeight; button.frame = CGRectMake(0, 0, 60, 44); [button setImage:[UIImage imageNamed:@"nav_menu_normal.png"] forState:UIControlStateNormal]; button.contentEdgeInsets = UIEdgeInsetsMake(2.5, 2.5, 2.5, 2.5); [button addTarget:self action:@selector(leftBarButtonItemAction:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; } [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Identifier"]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)chatActionFired { STDChatViewController *chatViewController = [[STDChatViewController alloc] initWithPageInfo:nil]; chatViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:chatViewController animated:YES]; } - (void)recordActionFired { STDRecordViewController *recordViewController = STDRecordViewController.new; [self.st_navigationController pushViewController:recordViewController animated:YES]; } - (void)avcActionFired { STARootViewController *avc = [[STARootViewController alloc] initWithStyle:UITableViewStyleGrouped]; [self.st_navigationController pushViewController:avc animated:YES]; } - (void)readerActionFired { STDReaderViewController *readerViewController = STDReaderViewController.new; [self.st_navigationController pushViewController:readerViewController animated:YES]; } - (void)leftBarButtonItemAction:(id)sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDAuthorization.h ================================================ // // STDAuthorization.h // STKitDemo // // Created by SunJiangting on 13-11-28. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import /** * @abstract 认证之后的操作 */ typedef enum { STAuthorizationOperationNone, // 认证失败之后不进行任何操作 STAuthorizationOperationAlert = 1 << 0,// 认证之后进行弹框提示 STAuthorizationOperationBanner = 1 << 1,// 认证之后进行横幅提示 } STAuthorizationOperation; /** * @abstract 自动认证的时机 */ typedef enum { STAutomicAuthorizationNever, // 从不进行自动认证 STAutomicAuthorizationDidFinishLaunch, // 应用每次启动的时候认证 STAutomicAuthorizationDidEnterForeground, // 应用每次进入前台之后认证 } STAutomicAuthorizationTime; @interface STDAuthorization : NSObject + (instancetype)standardAuthorization; + (void)setAuthorizationKey:(NSString *)authorizationKey; + (NSString *)authorizationKey; + (void)authorizationWithKey:(NSString *)key authorizationTime:(STAutomicAuthorizationTime)authorizationTime; @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDAuthorization.m ================================================ // // STDAuthorization.m // STKitDemo // // Created by SunJiangting on 13-11-28. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDAuthorization.h" #import #import NSString *const STDAuthorizationKey = @"com.suen.authorzation.key"; static NSString *_authorizatonKey; static UIWindow *_displayWindow; @interface STDAuthorization () @property(nonatomic, strong) STNotificationWindow *notificationWindow; @end @implementation STDAuthorization + (void)load { [self standardAuthorization]; } + (instancetype)standardAuthorization { static dispatch_once_t onceToken; static STDAuthorization *_authorization; dispatch_once(&onceToken, ^{ _authorization = [[STDAuthorization alloc] init]; }); return _authorization; } + (void)setAuthorizationKey:(NSString *)authorizationKey { _authorizatonKey = authorizationKey; } + (NSString *)authorizationKey { return _authorizatonKey; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (instancetype)init { self = [super init]; if (self) { [[self class] setAuthorizationKey:STDAuthorizationKey]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidFinishLaunching:) name:UIApplicationDidFinishLaunchingNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; } return self; } - (void)applicationDidFinishLaunching:(id)sender { [[self class] authorizationWithKey:_authorizatonKey authorizationTime:STAutomicAuthorizationDidFinishLaunch]; } - (void)applicationWillEnterForeground:(id)sender { [[self class] authorizationWithKey:_authorizatonKey authorizationTime:STAutomicAuthorizationDidEnterForeground]; } + (NSString *)generateSigWithDictionary:(NSDictionary *)dictionary { NSMutableString *joinedString = [NSMutableString string]; NSArray *keys = [dictionary.allKeys sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; for (NSString *key in keys) { id value = [dictionary valueForKey:key]; if ([value isKindOfClass:[NSNumber class]]) { value = [value stringValue]; } if ([value isKindOfClass:[NSString class]]) { [joinedString appendString:key]; [joinedString appendString:@"="]; [joinedString appendString:value]; } } return [joinedString copy]; } + (void)authorizationWithKey:(NSString *)key authorizationTime:(STAutomicAuthorizationTime)authorizationTime { NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:5]; NSBundle *bundle = [NSBundle mainBundle]; NSString *version = [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]; [parameters setValue:bundle.bundleIdentifier forKey:@"bundle"]; [parameters setValue:version forKey:@"version"]; [parameters setValue:@(authorizationTime) forKey:@"authorizationTime"]; NSString *sig = [self generateSigWithDictionary:parameters]; if (sig.length > 50) { sig = [sig substringWithRange:NSMakeRange(0, 50)]; } [parameters setValue:[sig st_md5String] forKey:@"sig"]; [parameters setValue:@([[NSDate date] timeIntervalSince1970]) forKey:@"timestamp"]; STHTTPOperation *operation = [STHTTPOperation operationWithURLString:@"http://xstore.duapp.com/authorized/auth.action/" HTTPMethod:@"POST" parameters:parameters]; NSString *const cer = @"MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq"; STNetworkConfiguration *configuration = [[STNetworkConfiguration alloc] init]; STCertificateItem *item = [STCertificateItem certificateItemWithBase64String:cer]; if (item) { configuration.certificates = @[item]; } configuration.SSLPinningMode = STSSLPinningModeCertificate; configuration.allowsAnyHTTPSCertificate = NO; operation.configuration = configuration; if ([STLocationManager sharedManager].location) { NSString *location = [NSString stringWithFormat:@"%lf,%lf", [STLocationManager sharedManager].location.coordinate.longitude, [STLocationManager sharedManager].location.coordinate.latitude]; [operation addValue:location forHTTPHeaderField:@"User-Location"]; } [[STHTTPNetwork defaultHTTPNetwork] sendHTTPOperation:operation completionHandler:^(STHTTPOperation *operation, id response, NSError *error) { [self _handleHTTPOperation:operation response:response error:error]; }]; } + (void)_handleHTTPOperation:(STHTTPOperation *)operation response:(id)response error:(NSError *)error { if (error || ![response isKindOfClass:[NSDictionary class]] || !([[response valueForKey:@"denied"] boolValue])) { return; } NSDictionary *responseDict = response; /// 拒绝 NSDictionary *info = [responseDict valueForKey:@"info"]; NSInteger op = [[info valueForKey:@"operation"] intValue]; if (operation == STAuthorizationOperationNone) { return; } NSString *title = [info valueForKey:@"title"]; NSString *message = [info valueForKey:@"message"]; NSString *cancel = [info valueForKey:@"cancel"]; NSString *confirm = [info valueForKey:@"confirm"]; if (STGetBitOffset(op, 0)) { [UIApplication sharedApplication].keyWindow.userInteractionEnabled = YES; if ([[UIApplication sharedApplication] isIgnoringInteractionEvents]) { [[UIApplication sharedApplication] endIgnoringInteractionEvents]; } UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:cancel otherButtonTitles:confirm, nil]; [alertView st_showWithDismissBlock:^(UIAlertView *alertView, NSUInteger dismissIndex) { }]; } if (STGetBitOffset(op, 1)) { NSMutableDictionary *notificationInfo = [NSMutableDictionary dictionaryWithCapacity:5]; [notificationInfo setValue:title forKey:STNotificationViewTitleTextKey]; [notificationInfo setValue:message forKey:STNotificationViewDetailTextKey]; STNotificationView *notificationView = [STNotificationWindow notificationViewWithInfo:notificationInfo]; [[STDAuthorization standardAuthorization].notificationWindow pushNotificationView:notificationView animated:YES]; } } #pragma mark - STNotificationWindow - (STNotificationWindow *)notificationWindow { if (!_notificationWindow) { _notificationWindow = [[STNotificationWindow alloc] init]; _notificationWindow.notificationWindowDelegate = self; _notificationWindow.displayDuration = 20; } return _notificationWindow; } - (void)allNoticationViewDismissed { self.notificationWindow = nil; } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDDebugPingViewController.h ================================================ // // STDDebugPingViewController.h // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDDebugPingViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDDebugPingViewController.m ================================================ // // STDDebugPingViewController.m // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDDebugPingViewController.h" #import "STDebugFoundation.h" #import "STDPingServices.h" @interface STDDebugPingViewController () @property(nonatomic, strong) UITextField *textField; @property(nonatomic, strong) STDebugTextView *textView; @property(nonatomic, strong) STDPingServices *pingServices; @end @implementation STDDebugPingViewController - (void)dealloc { [self.pingServices cancel]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"Ping网络"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Clear" target:self action:@selector(_clearDebugViewActionFired:)]; if ([UIViewController instancesRespondToSelector:@selector(setEdgesForExtendedLayout:)]) { self.edgesForExtendedLayout = UIRectEdgeNone; } self.view.backgroundColor = [UIColor whiteColor]; self.textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, self.view.width - 100, 30)]; self.textField.borderStyle = UITextBorderStyleRoundedRect; self.textField.placeholder = @"请输入IP地址或者域名"; self.textField.text = @"suenblog.duapp.com"; [self.view addSubview:self.textField]; UIButton *goButton = [UIButton buttonWithType:UIButtonTypeCustom]; goButton.frame = CGRectMake(self.textField.right + 10, 10, 60, 30); [goButton setTitle:@"Ping" forState:UIControlStateNormal]; [goButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [goButton addTarget:self action:@selector(_pingActionFired:) forControlEvents:UIControlEventTouchUpInside]; goButton.tag = 10001; [self.view addSubview:goButton]; self.textView = [[STDebugTextView alloc] initWithFrame:CGRectMake(0, self.textField.bottom + 10, self.view.width, self.view.height - self.textField.bottom - 20)]; self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.textView.editable = NO; [self.view addSubview:self.textView]; } - (void)_clearDebugViewActionFired:(id)sender { self.textView.text = nil; } - (void)_pingActionFired:(UIButton *)button { // [SimplePingHelper ping:self.textField.text target:self sel:@selector(_pingCallback:)]; [self.textField resignFirstResponder]; if (button.tag == 10001) { __weak STDDebugPingViewController *weakSelf = self; [button setTitle:@"Stop" forState:UIControlStateNormal]; button.tag = 10002; self.pingServices = [STDPingServices startPingAddress:self.textField.text callbackHandler:^(STDPingItem *pingItem, NSArray *pingItems) { if (pingItem.status != STDPingStatusFinished) { [weakSelf.textView appendText:pingItem.description]; } else { [weakSelf.textView appendText:[STDPingItem statisticsWithPingItems:pingItems]]; [button setTitle:@"Ping" forState:UIControlStateNormal]; button.tag = 10001; weakSelf.pingServices = nil; } }]; } else { [self.pingServices cancel]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDLocationPickerController.h ================================================ // // STDLocationPickerController.h // STKitDemo // // Created by SunJiangting on 15-2-27. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDLocationPickerController : STDViewController + (CLLocationCoordinate2D)cachedFakeLocationCoordinate; @end extern NSString *const STFakeLocationCoordinateCacheKey; ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDLocationPickerController.m ================================================ // // STDLocationPickerController.m // STKitDemo // // Created by SunJiangting on 15-2-27. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDLocationPickerController.h" #import @interface STAnnotation : NSObject @property(nonatomic, copy) NSString *title; @property(nonatomic, copy) NSString *subtitle; @end @implementation STAnnotation @synthesize coordinate = _coordinate; - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate { _coordinate = newCoordinate; } - (NSString *)title { return _title; } - (NSString *)subtitle { return _subtitle; } @end @interface STDLocationPickerController () @property(nonatomic, strong) MKMapView *mapView; @end @implementation STDLocationPickerController - (void)dealloc { [[self class] setCachedRegion:self.mapView.region]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"模拟当前位置"; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"清除" target:self action:@selector(_clearFakeLocations:)]; self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.mapView.showsUserLocation = YES; self.mapView.delegate = self; [[STLocationManager sharedManager] requestWhenInUseAuthorization]; [self.view addSubview:self.mapView]; MKCoordinateRegion region = [[self class] cachedRegion]; if (region.center.longitude * region.center.latitude != 0) { [self.mapView setRegion:[[self class] cachedRegion] animated:YES]; } UILongPressGestureRecognizer *gestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(_longPressGestureRecognizerActionFired:)]; gestureRecognizer.minimumPressDuration = 0.5f; gestureRecognizer.delaysTouchesBegan = NO; [self.mapView addGestureRecognizer:gestureRecognizer]; CLLocationCoordinate2D coordinate2D = [[self class] cachedFakeLocationCoordinate]; if (coordinate2D.latitude * coordinate2D.longitude != 0) { [self _reloadLocateAnnotationWithCoordinate:coordinate2D]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)_clearFakeLocations:(id)sender { CLLocationCoordinate2D coordinate2D = {0.0, 0.0}; [[self class] setCachedFakeLocationCoordinate:coordinate2D]; NSMutableArray *annotations = [NSMutableArray arrayWithCapacity:1]; [self.mapView.annotations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if ([obj isKindOfClass:[STAnnotation class]]) { [annotations addObject:obj]; } }]; [self.mapView removeAnnotations:annotations]; } - (void)_longPressGestureRecognizerActionFired:(UILongPressGestureRecognizer *)longPressGestureRecognizer { if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan) { CGPoint point = [longPressGestureRecognizer locationInView:self.mapView]; CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; longPressGestureRecognizer.enabled = NO; longPressGestureRecognizer.enabled = YES; [[self class] setCachedFakeLocationCoordinate:coordinate]; [self _reloadLocateAnnotationWithCoordinate:coordinate]; } } - (void)_reloadLocateAnnotationWithCoordinate:(CLLocationCoordinate2D)coordinate { STAnnotation *annotation = [[self.mapView annotations] st_firstObjectOfClass:[STAnnotation class]]; if (!annotation) { annotation = [[STAnnotation alloc] init]; } else { [self.mapView removeAnnotation:annotation]; } annotation.title = [NSString stringWithFormat:@"%.8f, %.8f", coordinate.longitude, coordinate.latitude]; annotation.coordinate = coordinate; [self.mapView addAnnotation:annotation]; } + (void)setCachedRegion:(MKCoordinateRegion)region { NSDictionary *coordinate = @{@"longitude":@(region.center.longitude), @"latitude":@(region.center.latitude), @"latitudeDelta":@(region.span.latitudeDelta), @"longitudeDelta":@(region.span.longitudeDelta)}; [[NSUserDefaults standardUserDefaults] setValue:coordinate forKey:@"STMapRegionCacheKey"]; [[NSUserDefaults standardUserDefaults] synchronize]; } + (MKCoordinateRegion)cachedRegion { NSDictionary *coordinate = [[NSUserDefaults standardUserDefaults] valueForKey:@"STMapRegionCacheKey"]; CLLocationCoordinate2D coordinate2D; coordinate2D.longitude = [coordinate[@"longitude"] doubleValue]; coordinate2D.latitude = [coordinate[@"latitude"] doubleValue]; MKCoordinateSpan span; span.latitudeDelta = [coordinate[@"latitudeDelta"] doubleValue]; span.longitudeDelta = [coordinate[@"longitudeDelta"] doubleValue]; MKCoordinateRegion region; region.center = coordinate2D; region.span = span; return region; } + (void)setCachedFakeLocationCoordinate:(CLLocationCoordinate2D)coordinate2D { NSDictionary *coordinate = @{@"longitude":@(coordinate2D.longitude), @"latitude":@(coordinate2D.latitude)}; [[NSUserDefaults standardUserDefaults] setValue:coordinate forKey:STFakeLocationCoordinateCacheKey]; [[NSUserDefaults standardUserDefaults] synchronize]; } + (CLLocationCoordinate2D)cachedFakeLocationCoordinate { NSDictionary *coordinate = [[NSUserDefaults standardUserDefaults] valueForKey:STFakeLocationCoordinateCacheKey]; CLLocationCoordinate2D coordinate2D; coordinate2D.longitude = [coordinate[@"longitude"] doubleValue]; coordinate2D.latitude = [coordinate[@"latitude"] doubleValue]; return coordinate2D; } @end NSString *const STFakeLocationCoordinateCacheKey = @"STFakeLocationCoordinateCacheKey"; ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDPingServices.h ================================================ // // STDPingServices.h // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "SimplePing.h" typedef NS_ENUM(NSInteger, STDPingStatus) { STDPingStatusDidStart, STDPingStatusDidReceivePacket, STDPingStatusDidTimeout, STDPingStatusFinished, }; @interface STDPingItem : NSObject @property(nonatomic) NSString *originalAddress; @property(nonatomic, copy) NSString *IPAddress; @property(nonatomic) NSUInteger dateBytesLength; @property(nonatomic) double timeMilliseconds; @property(nonatomic) NSInteger timeToLive; @property(nonatomic) NSInteger ICMPSequence; @property(nonatomic) STDPingStatus status; + (NSString *)statisticsWithPingItems:(NSArray *)pingItems; @end @interface STDPingServices : NSObject /// 超时时间, default 500ms @property(nonatomic) double timeoutMilliseconds; + (STDPingServices *)startPingAddress:(NSString *)address callbackHandler:(void(^)(STDPingItem *pingItem, NSArray *pingItems))handler; @property(nonatomic) NSInteger maximumPingTimes; - (void)cancel; @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDPingServices.m ================================================ // // STDPingServices.m // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDPingServices.h" @implementation STDPingItem - (NSString *)description { if (self.status == STDPingStatusDidStart) { return [NSString stringWithFormat:@"PING %@ (%@): %ld data bytes",self.originalAddress, self.IPAddress, (long)self.dateBytesLength]; } if (self.status == STDPingStatusDidTimeout) { return [NSString stringWithFormat:@"Request timeout for icmp_seq %ld", (long)self.ICMPSequence]; } if (self.status == STDPingStatusDidReceivePacket) { return [NSString stringWithFormat:@"%ld bytes from %@: icmp_seq=%ld ttl=%ld time=%.3f ms", (long)self.dateBytesLength, self.IPAddress, (long)self.ICMPSequence, (long)self.timeToLive, self.timeMilliseconds]; } return super.description; } + (NSString *)statisticsWithPingItems:(NSArray *)pingItems { // --- baidu.com ping statistics --- // 5 packets transmitted, 5 packets received, 0.0% packet loss // round-trip min/avg/max/stddev = 4.445/9.496/12.210/2.832 ms NSString *address = [pingItems.firstObject originalAddress]; NSMutableString *description = [NSMutableString stringWithCapacity:50]; [description appendFormat:@"--- %@ ping statistics ---\n", address]; __block NSInteger receivedCount = 0; [pingItems enumerateObjectsUsingBlock:^(STDPingItem *obj, NSUInteger idx, BOOL *stop) { if (obj.status == STDPingStatusDidReceivePacket) { receivedCount ++; } }]; NSInteger allCount = pingItems.count; CGFloat lossPercent = (CGFloat)(allCount - receivedCount) / MAX(1.0, allCount) * 100; [description appendFormat:@"%ld packets transmitted, %ld packet received, %.1f%% packet loss\n", (long)allCount, (long)receivedCount, lossPercent]; return [description stringByReplacingOccurrencesOfString:@".0%" withString:@"%"]; } @end @interface STDPingServices () { BOOL _hasStarted; BOOL _isTimeout; NSInteger _repingTimes; NSInteger _icmpSequence; NSMutableArray *_pingItems; } @property(nonatomic, copy) NSString *address; @property(nonatomic, strong) SimplePing *simplePing; @property(nonatomic, strong)void(^callbackHandler)(STDPingItem *item, NSArray *pingItems); @end @implementation STDPingServices + (STDPingServices *)startPingAddress:(NSString *)address callbackHandler:(void(^)(STDPingItem *item, NSArray *pingItems))handler { STDPingServices *services = [[STDPingServices alloc] initWithAddress:address]; services.callbackHandler = handler; [services startPing]; return services; } - (instancetype)initWithAddress:(NSString *)address { self = [super init]; if (self) { self.timeoutMilliseconds = 500; self.address = address; self.simplePing = [SimplePing simplePingWithHostName:address]; self.simplePing.delegate = self; self.maximumPingTimes = 100; _icmpSequence = 1; _pingItems = [NSMutableArray arrayWithCapacity:10]; } return self; } - (void)startPing { _icmpSequence = 1; _repingTimes = 0; _hasStarted = NO; [_pingItems removeAllObjects]; [self.simplePing start]; } - (void)reping { [self.simplePing stop]; [self.simplePing start]; } - (void)_timeoutActionFired { STDPingItem *pingItem = [[STDPingItem alloc] init]; pingItem.ICMPSequence = _icmpSequence; pingItem.originalAddress = self.address; pingItem.status = STDPingStatusDidTimeout; [self _handlePingItem:pingItem]; } - (void)_handlePingItem:(STDPingItem *)pingItem { if (pingItem.status == STDPingStatusDidReceivePacket || pingItem.status == STDPingStatusDidTimeout) { [_pingItems addObject:pingItem]; } if (_repingTimes < self.maximumPingTimes - 1) { if (self.callbackHandler) { self.callbackHandler(pingItem, [_pingItems copy]); } _repingTimes ++; _icmpSequence ++; NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(reping) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; } else { if (self.callbackHandler) { self.callbackHandler(pingItem, [_pingItems copy]); } [self cancel]; } } - (void)cancel { [self.simplePing stop]; STDPingItem *pingItem = [[STDPingItem alloc] init]; pingItem.status = STDPingStatusFinished; if (self.callbackHandler) { self.callbackHandler(pingItem, [_pingItems copy]); } [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(_timeoutActionFired) object:nil]; } - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address { [pinger sendPingWithData:nil]; [self performSelector:@selector(_timeoutActionFired) withObject:nil afterDelay:self.timeoutMilliseconds / 1000.0]; } // If this is called, the SimplePing object has failed. By the time this callback is // called, the object has stopped (that is, you don't need to call -stop yourself). // IMPORTANT: On the send side the packet does not include an IP header. // On the receive side, it does. In that case, use +[SimplePing icmpInPacket:] // to find the ICMP header within the packet. - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet ICMPHeader:(ICMPHeader *)_ICMPHeader { STDPingItem *pingItem = [[STDPingItem alloc] init]; pingItem.IPAddress = pinger.IPAddress; pingItem.originalAddress = self.address; pingItem.dateBytesLength = packet.length - sizeof(ICMPHeader); pingItem.status = STDPingStatusDidStart; if (self.callbackHandler && !_hasStarted) { self.callbackHandler(pingItem, nil); _hasStarted = YES; } } // Called whenever the SimplePing object tries and fails to send a ping packet. - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet timeElasped:(NSTimeInterval)timeElasped { [[self class] cancelPreviousPerformRequestsWithTarget:self selector:@selector(_timeoutActionFired) object:nil]; const struct IPHeader * ipPtr = NULL; size_t ipHeaderLength; if (packet.length >= (sizeof(IPHeader) + sizeof(ICMPHeader))) { ipPtr = (const IPHeader *) [packet bytes]; ipHeaderLength = (ipPtr->versionAndHeaderLength & 0x0F) * sizeof(uint32_t); } NSInteger timeToLive = 0, dataBytesSize = 0; if (ipPtr != NULL) { dataBytesSize = packet.length - ipHeaderLength; timeToLive = ipPtr->timeToLive; } STDPingItem *pingItem = [[STDPingItem alloc] init]; pingItem.IPAddress = pinger.IPAddress; pingItem.dateBytesLength = dataBytesSize; pingItem.timeToLive = timeToLive; pingItem.timeMilliseconds = timeElasped * 1000; pingItem.ICMPSequence = _icmpSequence; pingItem.originalAddress = self.address; pingItem.status = STDPingStatusDidReceivePacket; [self _handlePingItem:pingItem]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDebugFoundation.h ================================================ // // STDebugFoundation.h // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import #import "STDAuthorization.h" @interface STDebugTextView : UITextView - (void)appendText:(NSString *)text; @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/Debug/STDebugFoundation.m ================================================ // // STDebugFoundation.m // STKitDemo // // Created by SunJiangting on 15-3-9. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDebugFoundation.h" @implementation STDebugTextView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.backgroundColor = [UIColor blackColor]; self.textColor = [UIColor greenColor]; if ([self respondsToSelector:@selector(layoutManager)]) { self.layoutManager.allowsNonContiguousLayout = NO; } self.font = [UIFont systemFontOfSize:14]; self.editable = NO; } return self; } - (void)appendText:(NSString *)text { if (text.length == 0) { return; } if (self.text.length == 0) { self.text = text; } else { self.text = [NSString stringWithFormat:@"%@\n%@" , self.text, text]; [self scrollToBottomAnimated:YES]; } } - (void)scrollToBottomAnimated:(BOOL)animated { [self scrollRangeToVisible:NSMakeRange(self.text.length, 0)]; } - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { NSString *selectorName = NSStringFromSelector(action); return [selectorName hasPrefix:@"copy"] || [selectorName hasPrefix:@"select"]; } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDButton.h ================================================ // // STDButton.h // STKitDemo // // Created by SunJiangting on 15-3-31. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STDButton : STButton @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDButton.m ================================================ // // STDButton.m // STKitDemo // // Created by SunJiangting on 15-3-31. // Copyright (c) 2015年 SunJiangting. All rights reserved. // @implementation STDButton /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDFontViewController.h ================================================ // // STDFontViewController.h // STKitDemo // // Created by SunJiangting on 15-3-31. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STDFontViewController : STViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDFontViewController.m ================================================ // // STDFontViewController.m // STKitDemo // // Created by SunJiangting on 15-3-31. // Copyright (c) 2015年 SunJiangting. All rights reserved. // @implementation STDFontViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDMoreViewController.h ================================================ // // STDMoreViewController.h // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDTextTableViewController.h" @interface STDMoreViewController : STDTextTableViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDMoreViewController.m ================================================ // // STDMoreViewController.m // STKitDemo // // Created by SunJiangting on 13-12-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDMoreViewController.h" #import "STDAboutViewController.h" #import "STDAppDelegate.h" #import "STDSettingViewController.h" @interface STDMoreViewController () @property (nonatomic, strong) NSArray *dataSource; @end @implementation STDMoreViewController @dynamic dataSource; - (instancetype) initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { NSMutableArray *dataSource = [NSMutableArray arrayWithCapacity:5]; STDTableViewCellItem *item30 = [[STDTableViewCellItem alloc] initWithTitle:@"开源组件许可" target:self action:@selector(_openSourceLicenseActionFired)]; STDTableViewCellItem *item31 = [[STDTableViewCellItem alloc] initWithTitle:@"关于STKit" target:self action:@selector(_aboutActionFired)]; STDTableViewSectionItem *section3 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item30, item31]]; [dataSource addObject:section3]; STDTableViewCellItem *item40 = [[STDTableViewCellItem alloc] initWithTitle:@"退出" target:self action:@selector(_logoutActionFired)]; STDTableViewSectionItem *section4 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item40]]; [dataSource addObject:section4]; self.dataSource = dataSource; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"更多介绍"; [[STPersistence standardPersistence] setValue:@(YES) forKey:@"STHasEnteredAboutViewController"]; self.st_navigationBar.barTintColor = [UIColor st_colorWithRGB:0x32BBF8]; self.st_navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor whiteColor]}; if (self.st_tabBarController) { [self.st_tabBarController setBadgeValue:nil forIndex:2]; } if (self.st_sideBarController) { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.autoresizingMask = UIViewAutoresizingFlexibleHeight; button.frame = CGRectMake(0, 0, 60, 44); [button setImage:[UIImage imageNamed:@"nav_menu_normal.png"] forState:UIControlStateNormal]; button.contentEdgeInsets = UIEdgeInsetsMake(2.5, 2.5, 2.5, 2.5); [button addTarget:self action:@selector(_leftBarButtonItemAction:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; } [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Identifier"]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)_settingActionFired:(id)sender { STDSettingViewController *settingViewController = [[STDSettingViewController alloc] initWithStyle:UITableViewStyleGrouped]; settingViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:settingViewController animated:YES]; } - (void)_aboutActionFired { STDAboutViewController *aboutViewController = [[STDAboutViewController alloc] initWithNibName:nil bundle:nil]; [self.st_navigationController pushViewController:aboutViewController animated:YES]; } - (void)_openSourceLicenseActionFired { NSString *path = [[NSBundle mainBundle] pathForResource:@"licenses" ofType:@"html"]; STWebViewController *webViewController; if (path) { webViewController = [[STWebViewController alloc] initWithContentsOfFile:path]; } else { webViewController = [[STWebViewController alloc] initWithURLString:@"http://xstore.duapp.com/stkitdemo/licenses/"]; } webViewController.hidesBottomBarWhenPushed = YES; webViewController.webViewBarHidden = YES; [self.st_navigationController pushViewController:webViewController animated:YES]; // webViewController.st_navigationBar.barTintColor = [UIColor]; webViewController.st_navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor st_colorWithRGB:0x06365F], NSFontAttributeName:[UIFont systemFontOfSize:14.]}; } - (void)_logoutActionFired { STDAppDelegate *appDelegate = (STDAppDelegate *)[UIApplication sharedApplication].delegate; [appDelegate replaceRootViewController:[appDelegate startViewController] animationOptions:UIViewAnimationOptionTransitionFlipFromRight]; } - (void)_leftBarButtonItemAction:(id)sender { if (self.st_sideBarController.sideAppeared) { [self.st_sideBarController concealSideViewControllerAnimated:YES]; } else { [self.st_sideBarController revealSideViewControllerAnimated:YES]; } } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDNavigationSettingViewController.h ================================================ // // STDNavigationSettingViewController.h // STKitDemo // // Created by SunJiangting on 14-8-17. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDViewController.h" @interface STDNavigationSettingViewController : STDViewController @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDNavigationSettingViewController.m ================================================ // // STDNavigationSettingViewController.m // STKitDemo // // Created by SunJiangting on 14-8-17. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "STDNavigationSettingViewController.h" #import "STDLoadingView.h" @interface STDNavigationSettingViewController () { NSInteger _startY; } @property (weak, nonatomic) IBOutlet UISlider *edgeSettingSlider; @property (weak, nonatomic) IBOutlet UISlider *offsetSettingSlider; @property(strong, nonatomic) IBOutlet STDLoadingView *loadingView; @end @implementation STDNavigationSettingViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization self.hidesBottomBarWhenPushed = YES; } return self; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.edgesForExtendedLayout = UIRectEdgeNone; self.navigationItem.title = @"导航设置"; self.edgeSettingSlider.maximumValue = self.view.width; CGFloat value = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultEdgeOffset"] floatValue]; self.edgeSettingSlider.value = value; CGFloat value1 = [[[STPersistence standardPersistence] valueForKey:@"STDNavigationDefaultOffset"] floatValue]; self.offsetSettingSlider.maximumValue = self.view.width; self.offsetSettingSlider.value = value1; _startY = self.loadingView.top; } - (IBAction)navigationDistanceValueChanged:(UISlider *)sender { sender.value = (NSInteger) sender.value; [[STPersistence standardPersistence] setValue:@(sender.value) forKey:@"STDNavigationDefaultEdgeOffset"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"STDNavigationDefaultEdgeOffset" object:nil]; } - (IBAction)navigationOffsetValueChanged:(UISlider *)sender { sender.value = (NSInteger)sender.value; [[STPersistence standardPersistence] setValue:@(sender.value) forKey:@"STDNavigationDefaultOffset"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"STDNavigationDefaultOffset" object:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (IBAction)offsetValueChanged:(UISlider *)sender { CGFloat maximumValue = sender.maximumValue; CGFloat minimumValue = sender.minimumValue; CGFloat completion = sender.value/(maximumValue - minimumValue); self.loadingView.completion = completion; self.loadingView.top = (_startY + completion * 76); } @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDNavigationSettingViewController.xib ================================================ ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDSettingViewController.h ================================================ // // STDSettingViewController.h // STKitDemo // // Created by SunJiangting on 15-2-15. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDViewController.h" #import "STDTextTableViewController.h" @interface STDSettingViewController : STDTextTableViewController + (BOOL)allowsCustomNavigationTransition; + (BOOL)chatReceiveImage; + (BOOL)reduceTransitionAnimation; @end ================================================ FILE: STKitDemo/Classes/Modules/Settings/STDSettingViewController.m ================================================ // // STDSettingViewController.m // STKitDemo // // Created by SunJiangting on 15-2-15. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STDSettingViewController.h" #import "STDNavigationSettingViewController.h" #import "STDMessage.h" #import "STDLocationPickerController.h" #import "STDDebugPingViewController.h" @interface STDSettingViewController () @property(nonatomic, weak) STDTableViewCellItem *item20; @property(nonatomic, weak) STDTableViewCellItem *item21; @property(nonatomic, weak) STDTableViewCellItem *item22; @end @implementation STDSettingViewController + (BOOL)allowsCustomNavigationTransition { return [[[STPersistence standardPersistence] valueForKey:@"STDAllowsCustomNavigationTransition"] boolValue]; } + (BOOL)chatReceiveImage { return [[[STPersistence standardPersistence] valueForKey:@"STDChatAcceptImage"] boolValue]; } + (BOOL)reduceTransitionAnimation { return [[[STPersistence standardPersistence] valueForKey:@"STDReduceTransitionAnimation"] boolValue]; } - (instancetype)initWithStyle:(UITableViewStyle)tableViewStyle { self = [super initWithStyle:tableViewStyle]; if (self) { NSMutableArray * dataSource = [NSMutableArray arrayWithCapacity:5]; STDTableViewCellItem * item00 = [[STDTableViewCellItem alloc] initWithTitle:@"还原设置" target:self action:@selector(_resetSettingActionFired)]; STDTableViewCellItem * item01 = [[STDTableViewCellItem alloc] initWithTitle:@"模拟位置" target:self action:@selector(_fakeSettingActionFired)]; STDTableViewCellItem * item02 = [[STDTableViewCellItem alloc] initWithTitle:@"Ping测试" target:self action:@selector(_pingActionFired)]; STDTableViewSectionItem *section0 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item00, item01, item02]]; [dataSource addObject:section0]; STDTableViewCellItem *item10 = [[STDTableViewCellItem alloc] initWithTitle:@"导航设置" target:self action:@selector(_navigationSettingActionFired)]; STDTableViewSectionItem * section1 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item10]]; [dataSource addObject:section1]; STDTableViewCellItem *item20 = [[STDTableViewCellItem alloc] initWithTitle:@"允许自定义导航切换" target:self action:@selector(_allowSettingActionFired:)]; item20.switchStyle = YES; item20.checked = [[[STPersistence standardPersistence] valueForKey:@"STDAllowsCustomNavigationTransition"] boolValue]; self.item20 = item20; STDTableViewCellItem *item21 = [[STDTableViewCellItem alloc] initWithTitle:@"聊天接收图片" target:self action:@selector(_chatSettingActionFired:)]; item21.switchStyle = YES; item21.checked = [[[STPersistence standardPersistence] valueForKey:@"STDChatAcceptImage"] boolValue]; self.item21 = item21; STDTableViewCellItem *item22 = [[STDTableViewCellItem alloc] initWithTitle:@"减少切换动画" target:self action:@selector(_reduceAnimationActionFired:)]; item22.switchStyle = YES; item22.checked = [[[STPersistence standardPersistence] valueForKey:@"STDReduceTransitionAnimation"] boolValue]; self.item22 = item22; STDTableViewSectionItem * section2 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item20, item21, item22]]; [dataSource addObject:section2]; STDTableViewCellItem *item30 = [[STDTableViewCellItem alloc] initWithTitle:@"清空聊天记录" target:self action:@selector(_deleteAllMessages)]; STDTableViewCellItem *item31 = [[STDTableViewCellItem alloc] initWithTitle:@"清空本地缓存" target:self action:@selector(_cleanActionFired)]; STDTableViewSectionItem * section3 = [[STDTableViewSectionItem alloc] initWithSectionTitle:@"" items:@[item30, item31]]; [dataSource addObject:section3]; self.dataSource = dataSource; } return self; } - (void)reloadData { self.item20.checked = [[[STPersistence standardPersistence] valueForKey:@"STDAllowsCustomNavigationTransition"] boolValue]; self.item21.checked = [[[STPersistence standardPersistence] valueForKey:@"STDChatAcceptImage"] boolValue]; self.item22.checked = [[[STPersistence standardPersistence] valueForKey:@"STDReduceTransitionAnimation"] boolValue]; [self.tableView reloadData]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.navigationItem.title = @"设置"; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)_fakeSettingActionFired { STDLocationPickerController *pickerController = [[STDLocationPickerController alloc] init]; pickerController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:pickerController animated:YES]; } - (void)_pingActionFired { STDDebugPingViewController *pingViewController = [[STDDebugPingViewController alloc] init]; pingViewController.hidesBottomBarWhenPushed = YES; [self.st_navigationController pushViewController:pingViewController animated:YES]; } - (void)_allowSettingActionFired:(UISwitch *)uiswitch { if ([uiswitch isKindOfClass:[UISwitch class]]) { [[STPersistence standardPersistence] setValue:@(uiswitch.on) forKey:@"STDAllowsCustomNavigationTransition"]; [[NSNotificationCenter defaultCenter] postNotificationName:@"STDAllowsCustomNavigationTransitionDidChangeNotification" object:nil]; } } - (void)_reduceAnimationActionFired:(UISwitch *)uiswitch { if ([uiswitch isKindOfClass:[UISwitch class]]) { [[STPersistence standardPersistence] setValue:@(uiswitch.on) forKey:@"STDReduceTransitionAnimation"]; self.st_tabBarController.animatedWhenTransition = !uiswitch.on; } } - (void)_chatSettingActionFired:(UISwitch *)uiswitch { if ([uiswitch isKindOfClass:[UISwitch class]]) { [[STPersistence standardPersistence] setValue:@(uiswitch.on) forKey:@"STDChatAcceptImage"]; } } - (void)_resetSettingActionFired { [[STPersistence standardPersistence] removeAllCachedValues]; STIndicatorView * indicatorView = [STIndicatorView showInView:self.view animated:YES]; indicatorView.forceSquare = YES; indicatorView.indicatorType = STIndicatorTypeText; indicatorView.textLabel.text = @"还原完成"; [indicatorView hideAnimated:YES afterDelay:0.5]; indicatorView.blurEffectStyle = STBlurEffectStyleDark; [self reloadData]; } - (void)_cleanActionFired { NSFileManager *manager = [NSFileManager defaultManager]; NSString *imagePath = STImageCacheDirectory(); if ([manager fileExistsAtPath:imagePath isDirectory:NULL]) { CGFloat size = [[[manager attributesOfItemAtPath:imagePath error:nil] valueForKey:NSFileSize] floatValue]; [manager removeItemAtPath:imagePath error:nil]; STIndicatorView * indicatorView = [STIndicatorView showInView:self.view animated:YES]; indicatorView.forceSquare = YES; indicatorView.indicatorType = STIndicatorTypeText; indicatorView.textLabel.text = @"清理完毕"; indicatorView.detailLabel.text = [NSString stringWithFormat:@"释放了%.2fM", size / 1024.f]; [indicatorView hideAnimated:YES afterDelay:0.5]; indicatorView.blurEffectStyle = STBlurEffectStyleDark; } } - (void)_deleteAllMessages { STIndicatorView *indicatorView = [STIndicatorView showInView:self.view animated:YES]; indicatorView.textLabel.text = @"删除中"; indicatorView.blurEffectStyle = STBlurEffectStyleDark; indicatorView.forceSquare = YES; [[STDCoreDataManager chatDataManager] performBlockOnMainThread:^(NSManagedObjectContext *context) { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"STDMessage"]; NSArray *messages = [context executeFetchRequest:fetchRequest error:nil]; if (messages.count > 0) { [messages enumerateObjectsUsingBlock:^(STDMessage *obj, NSUInteger idx, BOOL *stop) { [context deleteObject:obj]; }]; [[STDCoreDataManager chatDataManager] saveManagedObjectContext:context error:nil]; } [indicatorView hideAnimated:YES afterDelay:1.5]; } completionHandler:^{ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ indicatorView.textLabel.text = @"已删除"; }); }]; } - (void)_navigationSettingActionFired { STDNavigationSettingViewController *settingViewController = [[STDNavigationSettingViewController alloc] initWithNibName:nil bundle:nil]; [self.st_navigationController pushViewController:settingViewController animated:YES]; } @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/Foundation+STKit.h ================================================ // // Foundation+STKit.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import #import ST_EXTERN void STExchangeSelectors(Class aClass, SEL oldSelector, SEL newSelector); ST_EXTERN void STClassAddMethod(Class aClass, SEL selector, Method method); /// 是否是某个类的子类 ST_EXTERN BOOL STClassIsKindOfClass(Class _class, Class parentClass); /// 根据基本类型+值,转换成NSValue, 不包含CGRect等等 ST_EXTERN NSValue *STCreateValueFromPrimitivePointer(void *pointer, const char *objCType); /// 某个类是否响应某个类方法 ST_EXTERN BOOL STClassRespondsToSelector(Class class, SEL aSelector); ST_EXTERN void STPrintClassMethods(Class cls); ST_EXTERN void STPrintClassProperities(Class cls); #pragma mark - STRadian Degree ST_EXTERN CGFloat STRadianToDegree(CGFloat radian); ST_EXTERN CGFloat STDegreeToRadian(CGFloat degree); ST_EXTERN NSString *STTemporaryDirectory(); ST_EXTERN NSString *STDocumentDirectory(); ST_EXTERN NSString *STLibiaryDirectory(); ST_EXTERN NSString *STCacheDirectory(); #pragma mark - BitOffset ST_EXTERN BOOL STGetBitOffset(NSInteger value, NSInteger offset); ST_EXTERN NSInteger STSetBitOffset(NSInteger value, NSInteger bit, BOOL t); ST_EXTERN NSInteger STCleanBitOffset(NSInteger value, NSInteger bit); @interface NSObject (STKit) /** * @brief 给全局变量赋值/读取 * * @param value 全局变量的新值 * @param varName 全局变量名称.PS:属性的话记得加下划线 _property * * @discussion 如果是基本类型的var的话需要将value转换成 void * * */ - (void)st_setValue:(id)value forVar:(NSString *)varName; - (id)st_valueForVar:(NSString *)varName; /** * @brief 该类是否响应某个selector的类方法 * * @param aSelector 类方法名称。 * * @attention 不要和对象的respondsToSelector:搞混了,这个是对于某个Class的 */ + (BOOL)st_classRespondsToSelector:(SEL)aSelector; @end @interface NSObject (STPerformSelector) /// 注明: 如果返回值为基本类型,struct除外,其余都转换为NSNumber。 如果返回值是struct。则转为NSValue, /// 如果selector不存在,则直接返回nil, 如果参数不足,则nil填充。如果selector参数类型为基本类型,则可以直接传NSNumber - (id)st_performSelector:(SEL)aSelector withObjects:(id)object, ... __attribute__((sentinel(0, 1))); @end @interface NSString (STKit) /// 是否包含子字符串 - (BOOL)st_contains:(NSString *)substring; /// 过滤空格 - (NSString *)st_stringByTrimingWhitespace; /// substring的range - (NSArray *)st_rangesOfString:(NSString *)string; /// 使用正则表达式将字符串分割,array中不包含正则表达式 - (NSArray *)st_componentsSeparatedByRegex:(NSString *)regex; /// ranges substring's range - (NSArray *)st_componentsSeparatedByRegex:(NSString *)regex ranges:(NSArray **)ranges; /// ranges 表示正则表达式的区间。 里面为字符串,使用 NSRangeFromString可以直接解析 - (NSArray *)st_componentsSeparatedByRegex:(NSString *)regex regexRanges:(NSArray **)ranges; - (NSArray *)st_componentsSeparatedByRegex:(NSString *)regex ranges:(NSArray **)ranges checkingResults:(NSArray **)checkingResults; - (NSString *)st_stringByAddingHTMLEscapes; - (NSString *)st_stringByReplacingHTMLEscapes; - (NSData *)st_UTF8EncodedData; /// md5 加密 - (NSString *)st_md5String; - (NSString *)st_sha1String; @end @interface NSData (STKit) + (NSData *)st_dataWithBase64EncodedString:(NSString *)base64String; - (NSString *)st_base64String; - (NSString *)st_UTF8String; - (NSString *)st_md5String; - (NSString *)st_hexString; @end typedef NS_ENUM(NSInteger, STBookSeekDirection) { STBookSeekDirectionForward = 1, STBookSeekDirectionReverse = 2, }; /// @require @interface NSString (STPagination) - (NSString *)st_reverseString; - (NSString *)st_substringWithSeekOffset:(NSUInteger)offset constrainedToSize:(CGSize)size direction:(STBookSeekDirection)direction attributes:(NSDictionary *)attributes; /** * @abstract 根据指定的大小,对字符串进行分页,计算出每页显示的字符串区间(NSRange) * * @param attributes *分页所需的字符串样式,需要指定字体大小,行间距等。iOS6.0以上请参见UIKit中NSAttributedString的扩展,iOS6.0以下请参考CoreText中的CTStringAttributes.h * @param size 需要参考的size。即在size区域内 */ - (NSArray *)st_paginationWithAttributes:(NSDictionary *)attributes constrainedToSize:(CGSize)size; @end @class UIFont; @interface NSString (STDrawSize) - (CGFloat)st_heightWithFont:(UIFont *)font constrainedToWidth:(CGFloat)size; @end #pragma mark - NSNotificationOnMainThread @interface NSNotificationCenter (STPostOnMainThread) - (void)st_postNotificationOnMainThread:(NSString *)aName; - (void)st_postNotificationOnMainThreadWithName:(NSString *)aName object:(id)anObject; - (void)st_postNotificationOnMainThreadWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo; @end /** * @abstract timer fired时候的回调 * * @param timer 所创建的timer * @param invalidate 是否invalidate当前的timer */ typedef void(^STTimerFiredHandler) (NSTimer * timer, BOOL *invalidate); /// 使用block的形式,简化timer的使用 @interface NSTimer (STBlock) + (NSTimer *)st_timerWithTimeInterval:(NSTimeInterval)timeInterval firedHandler:(STTimerFiredHandler)handler; + (NSTimer *)st_scheduledTimerWithTimeInterval:(NSTimeInterval)timeInterval firedHandler:(STTimerFiredHandler)handler; - (instancetype)st_initWithFireDate:(NSDate *)date interval:(NSTimeInterval)interval firedHandler:(STTimerFiredHandler)handler; @end #pragma mark - NSDateComponents @interface NSDate (STKit) @property(readonly) NSInteger year; @property(readonly) NSInteger month; @property(readonly) NSInteger day; @property(readonly) NSInteger hour; @property(readonly) NSInteger minute; @property(readonly) NSInteger second; @property(readonly) NSDateComponents *components; /// MS MillSecond + (NSDate *)st_dateWithMSTimeIntervalSince1970:(NSTimeInterval)millisecond; + (NSString *)st_dateWithTimeIntervalSince1970:(NSTimeInterval)millisecond format:(NSString *)format; + (NSString *)st_dateWithMSTimeIntervalSince1970:(NSTimeInterval)millisecond format:(NSString *)format; + (NSString *)st_timestampFormattedStringWithTimeIntervalSince1970:(NSTimeInterval)millisecond; - (NSString*)st_timestampFormattedString; @end #pragma mark - STJSON @interface NSData (STKitJSON) - (id)JSONValue; @end @interface NSString (STKitJSON) - (id)JSONValue; @end @interface NSDictionary (STKitJSON) + (id)dictionaryWithJSONString:(NSString *)JSONString; + (id)dictionaryWithJSONData:(NSData *)JSONData; - (NSString *)JSONString; @end @interface NSArray (STKitJSON) + (id)arrayWithJSONString:(NSString *)JSONString; + (id)arrayWithJSONData:(NSData *)JSONData; - (NSString *)JSONString; @end #pragma mark - STSecureAccessor @interface NSArray (STSecure) - (id)st_objectAtIndex:(NSUInteger)index; @end @interface NSDictionary (STSecure) - (NSInteger)st_integerValueForKey:(NSString *)key; - (long long)st_longLongValueForKey:(NSString *)key; - (int)st_intValueForKey:(NSString *)key; - (double)st_doubleValueForKey:(NSString *)key; - (BOOL)st_boolValueForKey:(NSString *)key; - (NSArray *)st_arrayValueForKey:(NSString *)key; - (NSDictionary *)st_dictionaryValueForKey:(NSString *)key; - (NSString *)st_stringValueForKey:(NSString *)key; - (NSString *)st_stringAtValueForKey:(NSString *)key; @end @interface NSArray (STClass) - (BOOL)st_containsClass:(Class)aClass; - (NSUInteger)st_indexOfClass:(Class)aClass; - (NSUInteger)st_firstIndexOfClass:(Class)aClass; - (NSUInteger)st_lastIndexOfClass:(Class)aClass; - (id)st_firstObjectOfClass:(Class)aClass; - (id)st_lastObjectOfClass:(Class)aClass; @end @interface NSDictionary (STURLQuery) /// connector is between key and value, separator are between each record /// eg. @{@"name":@"suen", @"age":@(24)} will be convert to name=suen&age=24 (connector=,separator&) - (NSString *)st_compontentsJoinedByConnector:(NSString *)connector separator:(NSString *)separator; /// URL - (NSString *)st_compontentsJoinedUsingURLStyle; + (instancetype)st_dictionaryWithURLQuery:(NSString *)URLQuery; @end @interface NSString (STNetwork) - (NSString *)st_stringByURLEncoded; - (NSString *)st_stringByURLDecoded; @end extern NSString *STGetMachineID(void); extern NSString *STKitGetVersion(void); ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/NSData+STGZip.h ================================================ // // NSData+STGZip.h // STKit // // Created by SunJiangting on 15-3-26. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import // 需要引入 zib #define STKit_STDefines_GZip 0 #if STKit_STDefines_GZip #import @interface NSData (STGZip) - (NSData *)st_compressDataUsingGZip; + (NSData *)st_dataWithZipCompressedData:(NSData *)data; @end #endif ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STAESCryptor.h ================================================ // // STAESCryptor.h // STKit // // Created by SunJiangting on 14-9-19. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import typedef NS_OPTIONS(NSInteger, STAESCryptorOptions){ STAESCryptorOptionsKeySize128 = 1 << 0, // default STAESCryptorOptionsKeySize192 = 1 << 1, STAESCryptorOptionsKeySize256 = 1 << 2, /// 如果需要加密的数据 不是整Key对应的size的整数倍,补全方式 STAESCryptorOptionsNoPadding = 1 << 8, STAESCryptorOptionsZerosPadding = 1 << 9, // 补0 STAESCryptorOptionsPKCS5Padding = 1 << 10, STAESCryptorOptionsPKCS7Padding = STAESCryptorOptionsPKCS5Padding, // default // 加密模式 STAESCryptorOptionsCBCMode = 1 << 15, // default STAESCryptorOptionsECBMode = 1 << 16, }; @interface STAESCryptor : NSObject /** * @abstract * @param key 密钥 * @param options default STAESCryptorOptionsKeySize128 | STAESCryptorOptionsPKCS7Padding | STAESCryptorOptionsCBCMode * @param iv 初始向量,默认为空,ECB模式下,这个参数无用 */ - (instancetype)initWithKey:(NSString *)key; - (instancetype)initWithKey:(NSString *)key options:(STAESCryptorOptions)options; - (instancetype)initWithKey:(NSString *)key options:(STAESCryptorOptions)options iv:(NSString *)iv; @property(nonatomic, copy, readonly) NSString *key; /// 初始向量, 默认为空。会根据 加密方式128,192,256 截取keysize。如果不足,则0填充 @property(nonatomic, copy, readonly) NSString *iv; @property(nonatomic, readonly) STAESCryptorOptions options; - (NSData *)encryptData:(NSData *)data; - (NSData *)decryptData:(NSData *)data; @end @interface NSData (STAESCryptor) /// default options STAESCryptorOptionsPKCS7Padding | STAESCryptorOptionsCBCMode - (NSData *)AES128EncryptedDataWithKey:(NSString *)key; - (NSData *)AES192EncryptedDataWithKey:(NSString *)key; - (NSData *)AES256EncryptedDataWithKey:(NSString *)key; - (NSData *)decryptAES128DataWithKey:(NSString *)key; - (NSData *)decryptAES192DataWithKey:(NSString *)key; - (NSData *)decryptAES256DataWithKey:(NSString *)key; - (NSData *)AESEncryptedDataWithKey:(NSString *)key options:(STAESCryptorOptions)options; - (NSData *)decryptAESWithKey:(NSString *)key options:(STAESCryptorOptions)options; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STAlbumManager.h ================================================ // // STAlbumManager.h // STKit // // Created by SunJiangting on 14-9-28. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @class UIImage; typedef void (^STAlbumSaveHandler)(UIImage *image, NSError *error); /** * @brief 将图片写入相册,使用ALAssetLibrary * * @param image 需要写入的图片 * @param album 相册名称,如果相册不存在,则新建相册 * @param completionHandler 回调 */ extern void STImageWriteToPhotosAlbum(UIImage *image, NSString *album, STAlbumSaveHandler completionHandler); @interface STAlbumManager : NSObject + (instancetype)sharedManager; /** * @brief 将图片写入相册,使用ALAssetLibrary * * @param image 需要写入的图片 * @param album 相册名称,如果相册不存在,则新建相册 * @param completionHandler 回调 */ - (void)saveImage:(UIImage *)image toAlbum:(NSString *)album completionHandler:(STAlbumSaveHandler)completionHandler; @end @interface ALAssetsLibrary (STAssetsLibrary) - (void)writeImage:(UIImage *)image toAlbum:(NSString *)album completionHandler:(STAlbumSaveHandler)completionHandler; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STApplicationContext.h ================================================ // // STApplicationContext.h // STKit // // Created by SunJiangting on 14-8-14. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import /** * @abstract 提供App运行时的一些状态 * */ @interface STApplicationContext : NSObject + (STApplicationContext *)sharedContext; @property(nonatomic, assign, readonly) NSString *name; @property(nonatomic, assign, readonly) NSString *bundleIdentifier; @property(nonatomic, assign, readonly) NSString *bundleVersion; /// 目前存在的所有UIAlertView @property(nonatomic, copy, readonly) NSArray *availableAlertViews; /// 界面主window,默认去从appdelegate中读取,如果没有读取到则返回占屏幕面积最大的window @property(nonatomic, assign, readonly) UIWindow *mainWindow; /// 目前显示的最顶端的ViewController @property(nonatomic, assign, readonly) UIViewController *topmostViewController; - (BOOL)openURL:(NSURL *)URL; - (BOOL)canOpenURL:(NSURL *)URL; /// when openURL, the context will enumerate all URLs to find the appropriate class. - (BOOL)registerClass:(Class)class forURLString:(NSString *)URLString; - (UIViewController *)topmostViewControllerExcludeClasses:(NSArray *)classes; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STAudioCenter.h ================================================ // // STAudioCenter.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import #import @interface STAudioCenter : NSObject + (instancetype)sharedAudioCenter; + (void)setAudioSessionEnabled:(BOOL)audioSessionEnabled wantRecording:(BOOL)wantRecording; /// 播放震动 - (void)playVibrations; @end @interface STAudioCenter (STAudioRecorder) @property(nonatomic, readonly, strong) STAudioRecorder *audioRecorder; - (void)startRecordWithPath:(NSString *)path handler:(STAudioRecordHandler)audioHandler; - (void)startRecordWithPath:(NSString *)path handler:(STAudioRecordHandler)audioHandler dataHandler:(STAudioDataHandler)dataHandler; - (void)finishRecord; @end extern NSString *const STAudioSessionOutputVolumeDidChangeNotification; extern NSString *const STAudioSessionOutputVolumeNewValueKey; extern NSString *const STAudioSessionOutputVolumeOldValueKey; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STAudioRecorder.h ================================================ // // STAudioRecorder.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import /// 录音状态 typedef NS_ENUM(NSInteger, STAudioRecorderState) { STAudioRecorderBegan, // 开始录音 STAudioRecorderProgressed, // 正在录音 STAudioRecorderEnded, STAudioRecorderCancelled, // 理论上该方法不会被调用。 STAudioRecorderFailed, // 录音失败,文件错误等等 }; /** * @abstract 录音回调 * * @param state 录音状态 * @param userInfo 录音中的一些数据,一般是NSDictionary。可以通过文件中定义的Key去获取一些值 * @param error 录音失败,失败原因。 */ typedef void (^STAudioRecordHandler)(STAudioRecorderState state, id userInfo, NSError *error); /** * @abstract 录音数据回调 * * @param buffer 音频数据 * @param error 录音失败,失败原因。 */ typedef void (^STAudioDataHandler)(AudioQueueBufferRef buffer, NSError *error); @interface STAudioRecorder : NSObject /// 是否在recordoing状态 @property(nonatomic, readonly) BOOL recording; /// 音频储存路径 @property(nonatomic, readonly) NSString *path; /// 音频采样率 default 44100,一旦开始录音,则不能改变sampleRate值,需要预先设置好sampleRate,然后开始录音 @property(nonatomic, assign) NSUInteger sampleRate; /** * @abstract 开始录音 * * @param path 音频文件将要保存的路径 * @param audioHandler 用于录音状态时界面的相应。该回调不会返回音频数据,每次需要绘制的时候则会回调,默认1s调用60次。 * * @discussion 录音时,界面如果需要响应,比如 显示音波效果等,就需要从audioHandler回调中取得值 */ // 以下两个方法均为录音方法。 如果需要得到原始音频数据,则需要使用第二个方法。 - (void)startRecordWithPath:(NSString *)path handler:(STAudioRecordHandler)audioHandler; // 该方法的两个回调没有先后顺序,没有必然联系。如果录音状态正常,则audioHandler会随着绘制周期而回调。dataHandler则为AudioQueue有数据了才会回调。 - (void)startRecordWithPath:(NSString *)path handler:(STAudioRecordHandler)audioHandler dataHandler:(STAudioDataHandler)dataHandler; - (void)pause; // 停止录音 - (void)stop; @end extern NSString *const STAudioRecorderKeyDuration; extern NSString *const STAudioRecorderKeyPeakPower; extern NSString *const STAudioRecorderKeyAveragePower; extern NSString *const STAudioRecorderKeyErrorDomain; extern NSString *const STAudioRecorderKeyErrorData; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STButton.h ================================================ // // STButton.h // STKit // // Created by SunJiangting on 14-3-25. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import /// 1、提供选中和高亮背景色 /// 2、此Button上的所有Subview。当Button处于highlighted状态,subview同样处于highlighted状态 /// 3、此按钮为了避免系统按钮上的image和title无法设置frame问题,申明了ButtonImageView和buttonTitleLabel。 @interface STButton : UIButton @property(nonatomic, assign) BOOL usingSystemLayout; @property(nonatomic, strong) UIColor *highlightedBackgroundColor; @property(nonatomic, strong) UIColor *selectedBackgroundColor; @end @interface STButton (STKit) @property(nonatomic, assign) NSString *normalTitle; @property(nonatomic, assign) NSString *highlightedTItle; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STCategories.h ================================================ // // STCategories.h // STKit // // Created by SunJiangting on 14-10-31. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #ifndef STKit_STCategories_h #define STKit_STCategories_h #import #endif ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STCollectionViewFlowLayout.h ================================================ // // STCollectionViewFlowLayout.h // STKit // // Created by SunJiangting on 14-5-8. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @protocol STCollectionViewFlowLayoutDelegate; /** * @abstract 支持每行的高度不一致 */ // UICollectionViewFlowLayout @interface STCollectionViewFlowLayout : UICollectionViewLayout @property(nonatomic, assign) NSUInteger numberOfColumns; /// 行、列边距 @property(nonatomic) CGFloat minimumLineSpacing; @property(nonatomic) CGFloat minimumInteritemSpacing; @property(nonatomic) CGSize itemSize; @property(nonatomic) UIEdgeInsets sectionInset; /** * @brief The calculated width of an item in the specified section. * @discussion * The width of an item is calculated based on number of columns, the collection view width, and the horizontal insets for that section. */ - (CGFloat)itemWidthInSectionAtIndex:(NSInteger)section; @end @protocol STCollectionViewFlowLayoutDelegate @end @interface UICollectionView (STHeaderFooterView) @property(nonatomic, strong) UIView *collectionHeaderView; @property(nonatomic, strong) UIView *collectionFooterView; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STControlDefines.h ================================================ // // STControlDefines.h // STKit // // Created by SunJiangting on 14-9-17. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #ifndef STKit_STControlDefines_h #define STKit_STControlDefines_h /** * @abstract 刷新控件各个阶段的状态 * @constant STRefreshControlStateNormal 默认情况下的状态 * @constant STRefreshControlStateReachedThreshold 达到临界条件,即将触发刷新事件 * @constant STRefreshControlStateRefreshing 正在刷新 */ typedef NS_ENUM(NSInteger, STRefreshControlState) { STRefreshControlStateNormal, STRefreshControlStateReachedThreshold, STRefreshControlStateLoading }; /** * @abstract 分页控件的各个状态 * @constant STPaginationControlStateNormal 默认情况下的状态 * @constant STPaginationControlStateLoading 达到临界条件,即将触发加载下一页事件 * @constant STPaginationControlStateFailed 加载失败 * @constant STPaginationControlStateReachedEnd 没有加载到更多东西 */ typedef NS_ENUM(NSInteger, STPaginationControlState) { STPaginationControlStateNormal, STPaginationControlStateLoading, STPaginationControlStateFailed, STPaginationControlStateReachedEnd, }; typedef NS_ENUM (NSInteger, STScrollDirectorState) { STScrollDirectorStateRefreshNormal = 1, STScrollDirectorStateRefreshReachedThreshold = 2, STScrollDirectorStateRefreshLoading = 3, STScrollDirectorStatePaginationNormal = 11, STScrollDirectorStatePaginationLoading = 12, STScrollDirectorStatePaginationFailed = 13, STScrollDirectorStatePaginationReachedEnd = 14, }; #endif ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STCoreDataManager.h ================================================ // // STCoreDataManager.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import typedef void(^ STCoreDataCompletionHandler)(void); ST_ASSUME_NONNULL_BEGIN /** * @abstract CoreData管理。 * */ @interface STCoreDataManager : NSObject /** * @param path xxx.sqlite3 */ - (instancetype)initWithModelName:(NSString *)modelName dbFilePath:(NSString *)path NS_DESIGNATED_INITIALIZER; - (STNULLABLE instancetype)init NS_DEPRECATED_IOS(2_0, 2_0, "Please use initWithModelName"); @property(STPROPERTYNULLABLE nonatomic, readonly, copy) NSString *modelName; @property(STPROPERTYNULLABLE nonatomic, readonly, copy) NSString *dbFilePath; /// 该Context始终在主线程中。 UIViewController的fetchResultsController @property(nonatomic, readonly) NSManagedObjectContext *managedObjectContext; /// 该Context始终在子线程,并且parentContext为楼上的Context。为了提升主线程的绘制效率,建议所有的保存操作都在此Context进行。 @property(nonatomic, readonly) NSManagedObjectContext *backgroundManagedObjectContext; - (NSManagedObjectContext *)dispatchManagedObjectContext; /** * @abstract 将block中的变换进行save操作 * * @param managedObjectContext 发生改变的managedObject */ - (BOOL)saveManagedObjectContext:(NSManagedObjectContext *)managedObjectContext error:(NSError **)error; // 以下方法分别为在 任意子线程,主线程,特定后台线程执行block /** * @abstract 将一些数据库的CRUD方法放在block中。 * * @param block 需要执行的代码段 * @param waitUntilDone 是否需要等待执行, 如果是NO,则立刻返回,將block添加到queue中等待执行 */ - (void)performBlock:(void (^)(NSManagedObjectContext *dispatchedContext))block completionHandler:(void (^ ST_NULLABLE)(void))completionHandler; - (void)performBlockOnMainThread:(void (^)(NSManagedObjectContext *mainContext))block completionHandler:(void (^ ST_NULLABLE)(void))completionHandler; - (void)performBlockInBackground:(void (^)(NSManagedObjectContext *backgroundContext))block completionHandler:(void (^ ST_NULLABLE)(void))completionHandler; @end @interface NSManagedObjectContext (STCoreDataManager) - (NSEntityDescription *)descriptionForEntityName:(NSString *)entityName; - (NSManagedObject *)entityClassFromString:(NSString *)className name:(NSString *)entityName; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STDefines.h ================================================ // // STDefines.h // STKit // // Created by SunJiangting on 13-11-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #ifndef STKit_STDefines_h #define STKit_STDefines_h #define ST_UNAVAILABLE(x) __attribute__((unavailable(x))) #if __has_feature(nullability) #define STNONNULL nonnull #define STPROPERTYNONNULL nonnull, #define ST_NONNULL __nonnull #define STNULLABLE nullable #define STPROPERTYNULLABLE nullable, #define ST_NULLABLE __nullable #define _STNULLABLE _Nullable #define _STNonnull _Nonnull #define ST_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN #define ST_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END #else #define STNONNULL #define STPROPERTYNONNULL #define ST_NONNULL #define STNULLABLE #define STPROPERTYNULLABLE #define ST_NULLABLE #define _STNULLABLE #define _STNonnull #define ST_ASSUME_NONNULL_BEGIN #define ST_ASSUME_NONNULL_END #endif #if !defined(ST_INLINE) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define ST_INLINE static inline #elif defined(__cplusplus) #define ST_INLINE static inline #elif defined(__GNUC__) #define ST_INLINE static __inline__ #else #define ST_INLINE static #endif #endif #if !defined(ST_EXTERN) #define ST_EXTERN extern #endif #import #import #ifndef DEBUG #ifdef STLog #undef STLog(format, ...) #define STLog(format, ...) #else #define STLog(format, ...) #endif #else #ifndef STLog #define STLog(format, ...) NSLog((@"%s [Line %d] " format), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #endif #endif #ifndef STLogStruct #define STLogStruct #define STLogPoint(point) STLog(@"Point (%f, %f)", point.x, point.y); #define STLogSize(size) STLog(@"Size (%f, %f)", size.width, size.height); #define STLogRect(rect) STLog(@"Rect (%f,%f,%f,%f)", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); #define STLogEdgeInsets(insets) STLog(@"EdgeInsets (%f,%f,%f,%f)", insets.top, insets.left, insets.bottom, insets.right); #endif ST_INLINE CGFloat STDistanceBetweenPoints(CGPoint point1, CGPoint point2) { CGFloat distance2 = ABS((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y)); return sqrtf(distance2); } /// 定义一种结构体,用来表示区间。表示一个 从 几到几 的概念 typedef struct _STRange { NSInteger start; NSInteger end; } STRange; /** * @brief 创建结构体 STRange,结构体中保存start,end * @param start 范围开始 * @param end 范围结束 * @return 返回 该范围 * @note eg. SRangeMake(0,5) 则返回 0~5 */ ST_INLINE STRange STRangeMake(NSInteger start, NSInteger end) { STRange range; range.start = start; range.end = end; return range; } /** * @brief 该int 数 是否在 STRange区间内 * @param r 整形区间 * @param i 要比较的数 * @return i在区间 r内,返回YES;否则,返回NO */ ST_INLINE BOOL STIsInRange(STRange r, NSInteger i) { return (r.start <= i) && (r.end >= i); } /** * @brief 该点是否在某一rect区间内 * @param p 点 * @param r 矩形 */ ST_INLINE BOOL CGPointInRect(CGPoint p, CGRect r) { return p.x > r.origin.x && p.x < (r.origin.x + r.size.width) && p.y > r.origin.y && p.y < (r.origin.y + r.size.height); } #endif ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STGIFGenerator.h ================================================ // // STGIFGenerator.h // STKit // // Created by SunJiangting on 14-11-8. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import #import typedef NS_ENUM(NSInteger, STGIFPropertyColorModel) { STGIFPropertyColorModelRGB, STGIFPropertyColorModelGray, STGIFPropertyColorModelCMYK, STGIFPropertyColorModelLab }; ST_ASSUME_NONNULL_BEGIN @interface STGIFProperty : NSObject + (STGIFProperty *)defaultGIFProperty; /// default YES @property(nonatomic, getter=hasGlobalColorMap) BOOL hasGlobalColorMap; /// default STGIFPropertyColorModelRGB @property(nonatomic) STGIFPropertyColorModel colorModel; /// default 8 @property(nonatomic) CGFloat depth; /// default 0 @property(nonatomic) NSInteger loopCount; @end @interface STGIFGenerator : NSObject - (instancetype)initWithProperty:(STNULLABLE STGIFProperty *)property; @property(nonatomic) CGSize preferredImageSize; - (void)appendImage:(UIImage *)image duration:(NSTimeInterval)duration; - (void)startGeneratorWithPath:(STNULLABLE NSString *)path completionHandler:(void(^ ST_NULLABLE)(NSString *))completionHandler; - (void)cancel; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STHTTPConfiguration.h ================================================ // // STHTTPConfiguration.h // STKit // // Created by SunJiangting on 15-2-6. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import /// 如果有file,会强制使用mutilpart/form-data /// 否则服务端不能接收数据,一般没有特殊需求就不要乱搞 typedef NS_ENUM(NSInteger, STHTTPRequestFormEnctype) { STHTTPRequestFormEnctypeURLEncoded, /// Default STHTTPRequestFormEnctypeMultipartData, /// 如果有文件/图片,会使用此格式 STHTTPRequestFormEnctypeTextPlain, /// 慎用。如果你不知道什么意思,你就不要用这个,一般服务器都不支持。 }; /// default text/json typedef NS_ENUM(NSInteger, STHTTPResponseDataType) { STHTTPResponseDataTypeTextHTML = 0, // 返回类型位HTML text/html STHTTPResponseDataTypeTextJSON = 1, // 返回类型位JSON text/json STHTTPResponseDataTypeTextXML = 2 // 返回类型位XML text/xml }; typedef NS_OPTIONS(NSInteger, STXMLParseOptions){ STXMLParseOptionsProcessNamespaces = 1 << 0, STXMLParseOptionsReportNamespacePrefixes = 1 << 1, STXMLParseOptionsResolveExternalEntities = 1 << 2, }; typedef NS_ENUM(NSInteger, STCompressionOptions) { STCompressionOptionsNone = 1 << 0, // 不接受任何压缩 STCompressionOptionsRequestAllowed = 1 << 1, // 请求时压缩request-body STCompressionOptionsResponseAccepted = 1 << 2 // 允许服务器传输压缩的数据 }; @interface STHTTPConfiguration : NSObject + (instancetype)defaultConfiguration; /// Expiration -1 means follow the protocol @property(nonatomic, getter=supportCachePolicy) BOOL supportCachePolicy; @property(nonatomic) NSURLRequestCachePolicy cachePolicy; @property(nonatomic, copy)NSString *HTTPMethod; @property(nonatomic) STCompressionOptions compressionOptions; @property(nonatomic) NSStringEncoding dataEncoding; // 是否自动解码 @property(nonatomic) BOOL decodeResponseData; // default text/json @property(nonatomic) STHTTPResponseDataType dataType; /// used when dataType is text/json @property(nonatomic) NSJSONReadingOptions JSONReadingOptions; /// used when dataType is text/xml @property(nonatomic) STXMLParseOptions XMLParseOptions; /// 元素内容的key.默认content @property(nonatomic, copy) NSString *XMLElementContextKey; /// 超时时间 default 60s @property(nonatomic) NSTimeInterval timeoutInterval; @property(nonatomic) STHTTPRequestFormEnctype enctype; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STHTTPNetwork.h ================================================ // // STHTTPNetwork.h // STKit // // Created by SunJiangting on 13-11-25. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import "STNetworkConfiguration.h" /// 100以下的是客户端错误, 100->600 之间的为标准的HTTP协议错误 typedef NS_ENUM(NSInteger, STHTTPNetworkErrorCode) { STHTTPNetworkErrorCodeUserCancelled = 1, STHTTPNetworkErrorCodeCantLoadCache = 10, /// 301跳转,永久重定向 STHTTPNetworkErrorCodeMovedTemporarily = 301, /// 302跳转,服务器redirect STHTTPNetworkErrorCodeMovedPermanently = 302, STHTTPNetworkErrorCodeServerForbidden = 403, STHTTPNetworkErrorCodePageNotFound = 404, STHTTPNetworkErrorCodeMethodNotAllowed = 405, STHTTPNetworkErrorCodeNotAcceptable = 406, // 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现 STHTTPNetworkErrorCodeInternetServerError = 500, STHTTPNetworkErrorCodeNotImplemented = 501, STHTTPNetworkErrorCodeBadGateway = 502, STHTTPNetworkErrorCodeServiceUnavailable = 503, STHTTPNetworkErrorCodeGatewayTimeout = 504, STHTTPNetworkErrorCodeHTTPVersionNotSupported = 505, STHTTPNetworkErrorCodeUnsupportedResponseDataType = 1001, // 不是预期的返回结果 STHTTPNetworkErrorCodeBadNetwork = -1, STHTTPNetworkErrorCodeTimeout = NSURLErrorTimedOut, // -1001 STHTTPNetworkErrorCodeOther = -97676901, }; @class STHTTPOperation; typedef void (^STHTTPNetworkHandler)(STHTTPOperation *operation, id response, NSError *error); typedef void (^STHTTPSynchronousNetworkHandler)(NSURLResponse *response, id data, NSError *error); /// HTTP类型的网络请求 @interface STHTTPNetwork : NSObject + (instancetype)defaultHTTPNetwork; + (NSURLCache *)defaultHTTPCache; @property(nonatomic, strong, readonly) NSURLSession *URLSession; - (instancetype)initWithConfiguration:(STNetworkConfiguration *)configuration; /// default mainQueue @property(nonatomic, strong) dispatch_queue_t callbackQueue; @property(nonatomic, assign) NSInteger maxConcurrentRequestCount; - (void)sendHTTPOperation:(STHTTPOperation *)operation; - (void)cancelHTTPOperation:(STHTTPOperation *)operation; @end @interface STHTTPNetwork (STHTTPConvenience) - (void)sendHTTPOperation:(STHTTPOperation *)operation completionHandler:(STHTTPNetworkHandler)completionHandler; - (STHTTPOperation *)sendRequestWithURLString:(NSString *)URLString parameters:(NSDictionary *)parameters completionHandler:(STHTTPNetworkHandler)completionHandler; @end extern NSString *const STHTTPNetworkErrorDomain; extern NSString *const STHTTPNetworkErrorDescriptionUserInfoKey; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STHTTPOperation.h ================================================ // // STHTTPOperation.h // STKit // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import "STHTTPRequest.h" #import "STNetworkConfiguration.h" #import @class STHTTPOperation; /// 即将开始网络请求,可以配置一些参数(cookies,headerfields等等) typedef void (^STHTTPWillStartHandler)(STHTTPOperation *operation); // 请求时时相应,下载资源等 /** * @abstract *网络请求时,服务器应答的回调,服务器有时候可能不是一次接受到所有数据,所以会分几次接受 * * @param data 服务端返回的数据 * @param completion 完成度,完成的百分比 */ typedef void (^STHTTPRequestProgressHandler)(STHTTPOperation *operation, CGFloat completionPercent); /** * @abstract 网络请求结束的回调 * * @param response 包含网络返回的数据 */ typedef void (^STHTTPResponseHandler)(STHTTPOperation *operation, id response); // 请求时时相应,下载资源等 /** * @abstract *网络请求时,服务器应答的回调,服务器有时候可能不是一次接受到所有数据,所以会分几次接受 * * @param data 服务端返回的数据 * @param completion 完成度,完成的百分比 */ typedef void (^STHTTPProgressHandler)(STHTTPOperation *operation, NSData *data, CGFloat completionPercent); typedef void (^STHTTPFinishedHandler)(STHTTPOperation *operation, NSData *data, NSError *error); @class STHTTPNetwork; @interface STHTTPOperation : NSOperation { @private STHTTPNetwork *_networkDelegate; } /// 所有的网络请求都在这个线程发送 + (NSThread *)standardNetworkThread; - (instancetype)initWithHTTPRequest:(STHTTPRequest *)request; @property(atomic, readonly) NSInteger identifier; @property(nonatomic, strong) STNetworkConfiguration *configuration; @property(nonatomic, strong, readonly) STHTTPRequest *request; @property(nonatomic, strong, readonly) NSHTTPURLResponse *HTTPResponse; @property(nonatomic, copy, readonly) NSData *responseData; @property(nonatomic, readonly) NSInteger HTTPStatusCode; @property (nonatomic, getter=isSynchronous) BOOL synchronous; // Return only a single result, blocking until available (or failure). Defaults to NO @property(nonatomic, strong) STHTTPWillStartHandler willStartHandler; /// 请求过程回调 @property(nonatomic, strong) STHTTPRequestProgressHandler requestProgressHandler; /// 收到请求应答回调 @property(nonatomic, strong) STHTTPResponseHandler responseHandler; /// 当Response比较大时,比如图片,音频,文件等会分批次接受,该回调为每次接收到的%比。参考Content-Length @property(nonatomic, strong) STHTTPProgressHandler progressHandler; /// 请求结束时的回调 @property(nonatomic, strong) STHTTPFinishedHandler finishedHandler; /// 请求时带的额外信息 @property(nonatomic, strong) NSDictionary *contextInfo; @end @interface STHTTPOperation (STHTTPRequest) + (instancetype)operationWithURLString:(NSString *)URLString parameters:(NSDictionary *)parameters; + (instancetype)operationWithURLString:(NSString *)URLString HTTPMethod:(NSString *)method parameters:(NSDictionary *)parameters; /*! @method setAllHTTPHeaderFields: @abstract Sets the HTTP header fields of the receiver to the given dictionary. @discussion This method replaces all header fields that may have existed before this method call.

Since HTTP header fields must be string values, each object and key in the dictionary passed to this method must answer YES when sent an -isKindOfClass:[NSString class] message. If either the key or value for a key-value pair answers NO when sent this message, the key-value pair is skipped. @param headerFields a dictionary containing HTTP header fields. */ - (void)setAllHTTPHeaderFields:(NSDictionary *)headerFields; /*! @method setValue:forHTTPHeaderField: @abstract Sets the value of the given HTTP header field. @discussion If a value was previously set for the given header field, that value is replaced with the given value. Note that, in keeping with the HTTP RFC, HTTP header field names are case-insensitive. @param value the header field value. @param field the header field name (case-insensitive). */ - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; /*! @method addValue:forHTTPHeaderField: @abstract Adds an HTTP header field in the current header dictionary. @discussion This method provides a way to add values to header fields incrementally. If a value was previously set for the given header field, the given value is appended to the previously-existing value. The appropriate field delimiter, a comma in the case of HTTP, is added by the implementation, and should not be added to the given value by the caller. Note that, in keeping with the HTTP RFC, HTTP header field names are case-insensitive. @param value the header field value. @param field the header field name (case-insensitive). */ - (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field; - (void)setParameter:(id )parameter forField:(NSString *)field; - (void)addParameter:(id )parameter forField:(NSString *)field; - (void)setHTTPConfiguration:(STHTTPConfiguration *)configuration; - (STHTTPConfiguration *)HTTPConfiguration; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STHTTPRequest.h ================================================ // // STHTTPRequest.h // STKit // // Created by SunJiangting on 15-2-4. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import #import ST_ASSUME_NONNULL_BEGIN @interface STMultipartItem : NSObject @property(nonatomic, copy) NSString *name; /// 如果传送文件 @property(STPROPERTYNULLABLE nonatomic, copy) NSString *path; /// 发送图片或者data @property(STPROPERTYNULLABLE nonatomic, copy) NSData *data; @property(STPROPERTYNULLABLE nonatomic, copy) NSString *MIMEType; @end @interface STHTTPRequest : NSObject @property(STPROPERTYNULLABLE nonatomic, copy)STHTTPConfiguration *HTTPConfiguration; - (instancetype)initWithURLString:(NSString *)URLString HTTPMethod:(NSString *)HTTPMethod parameters:(STNULLABLE NSDictionary *)parameters; + (instancetype)requestWithURLString:(NSString *)URLString HTTPMethod:(NSString *)HTTPMethod parameters:(STNULLABLE NSDictionary *)parameters; @property(nonatomic, copy, readonly) NSURLRequest *URLRequest; - (void)prepareToRequest; @end @interface STHTTPRequest (STHTTPHeader) /*! @method setAllHTTPHeaderFields: @abstract Sets the HTTP header fields of the receiver to the given dictionary. @discussion This method replaces all header fields that may have existed before this method call.

Since HTTP header fields must be string values, each object and key in the dictionary passed to this method must answer YES when sent an -isKindOfClass:[NSString class] message. If either the key or value for a key-value pair answers NO when sent this message, the key-value pair is skipped. @param headerFields a dictionary containing HTTP header fields. */ - (void)setAllHTTPHeaderFields:(STNULLABLE NSDictionary *)headerFields; /*! @method setValue:forHTTPHeaderField: @abstract Sets the value of the given HTTP header field. @discussion If a value was previously set for the given header field, that value is replaced with the given value. Note that, in keeping with the HTTP RFC, HTTP header field names are case-insensitive. @param value the header field value. @param field the header field name (case-insensitive). */ - (void)setValue:(STNULLABLE NSString *)value forHTTPHeaderField:(NSString *)field; /*! @method addValue:forHTTPHeaderField: @abstract Adds an HTTP header field in the current header dictionary. @discussion This method provides a way to add values to header fields incrementally. If a value was previously set for the given header field, the given value is appended to the previously-existing value. The appropriate field delimiter, a comma in the case of HTTP, is added by the implementation, and should not be added to the given value by the caller. Note that, in keeping with the HTTP RFC, HTTP header field names are case-insensitive. @param value the header field value. @param field the header field name (case-insensitive). */ - (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field; - (void)setParameter:(STNULLABLE id )parameter forField:(NSString *)field; - (void)addParameter:(id )parameter forField:(NSString *)field; @end @interface NSString (STURLParameters) - (NSString *)stringByAppendingURLParameters:(NSDictionary *)parameters; @end ST_EXTERN NSString *STJoinQueryComponentsWithParameters(NSDictionary *parameters); ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImage.h ================================================ // // STImage.h // STKit // // Created by SunJiangting on 14-11-8. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STImage : UIImage @property(nonatomic, assign, readonly, getter=isGIFImage) BOOL GIFImage; @property(nonatomic, assign, readonly) NSInteger numberOfImages; - (UIImage *)imageAtIndex:(NSInteger)index duration:(NSTimeInterval *)duration; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageCache.h ================================================ // // STImageCache.h // STKit // // Created by SunJiangting on 13-12-17. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import typedef long long STIdentifier; extern NSString *STImageCacheDirectory(); extern STIdentifier STImageCacheBeginContext(); extern void STImageCachePushContext(STIdentifier contextId); extern void STImageCachePopContext(STIdentifier contextId); @class UIImage; @interface STImageCache : NSObject /// 将图片缓存到文件 /** * @abstract 将图片缓存到文件,读取时需要通过key。图片会存储在Document下的某一目录 * * @param image 需要缓存的图片 * @param key 一般为图片的URL */ + (void)cacheImage:(UIImage *)image forKey:(NSString *)key; + (void)removeCacheImageForKey:(NSString *)key; + (void)removeMemoryCacheForKey:(NSString *)key; + (BOOL)hasMemoryCacheForKey:(NSString *)key; + (void)removeCachedImagesBeforeDate:(NSDate *)date completionHandler:(void(^)())completionHandler; /** * @abstract 得到该key的图片缓存目录 */ + (NSString *)cachedPathForKey:(NSString *)key; /// 是否有缓存该图片 + (BOOL)hasCachedImageForKey:(NSString *)key; + (UIImage *)cachedImageForKey:(NSString *)key; + (void)cacheData:(NSData *)data forKey:(NSString *)key; + (NSData *)cachedDataForKey:(NSString *)key; + (unsigned long long)cacheSize; /// default backgroundQueue / DISPATCH_QUEUE_PRIORITY_BACKGROUND + (void)calculateCacheSizeWithCompletionHandler:(void(^)(CGFloat))completionHandler; + (void)calculateCacheSizeInQueue:(dispatch_queue_t)backgroundQueue completionHandler:(void(^)(CGFloat))completionHandler; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageCollectionView.h ================================================ // // STImageCollectionView.h // STKit // // Created by SunJiangting on 14-8-25. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @protocol STImageCollectionViewDelegate; @class STImageScrollView; @interface STImageCollectionView : UIView - (instancetype)initWithFrame:(CGRect)frame images:(NSArray *)images; @property(nonatomic, copy) NSArray *images; - (void)setImages:(NSArray *)images animated:(BOOL)animated; @property(nonatomic, assign) NSUInteger currentImageIndex; // default is 0. value pinned to 0..images.count-1 @property(nonatomic, weak) id delegate; @property(nonatomic, assign) CGFloat horizontalSpacing; @property(nonatomic, strong, readonly) UICollectionView *collectionView; @property(nonatomic, strong, readonly) STImageScrollView *imageScrollView; @end @protocol STImageCollectionViewDelegate @optional - (void)imageCollectionView:(STImageCollectionView *)collectionView didDisplayImageAtIndex:(NSInteger)index; - (void)imageCollectionView:(STImageCollectionView *)collectionView didTapImageAtIndex:(NSInteger)index; - (void)imageCollectionView:(STImageCollectionView *)collectionView didLongPressImage:(UIImage *)image atIndex:(NSInteger)index; @end @interface STImageItem : STObject @property(nonatomic, strong) UIImage *thumb; @property(nonatomic, copy) NSString *thumbURLString; @property(nonatomic, strong) UIImage *image; @property(nonatomic, copy) NSString *imageURLString; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageLoader.h ================================================ // // STImageLoader.h // STKit // // Created by SunJiangting on 13-10-29. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import #import /** * @abstract 图片文件下载完成回调 * * @param image 下载完成之后的image * @param error 文件下载失败的错误 */ typedef void (^STImageLoaderHandler)(UIImage *image, NSString *URLString, BOOL usingCache, NSError *error); /** * @abstract 图片下载完成度回调 * * @param completion 完成百分比 */ typedef void (^STImageProgressHandler)(CGFloat completion); /** * @abstract 图片下载顺序 * * STImageDownloadOrderForward 遵循FIFO,先请求,优先下载 * STImageDownloadOrderBackward 遵循LIFO, 后请求,先下载 */ typedef NS_ENUM(NSInteger, STImageDownloadOrder) { STImageDownloadOrderForward, STImageDownloadOrderBackward, }; /** * @abstract 图片下载器, 可以负责图片下载,下载进度回调等. * */ @interface STImageLoader : NSObject /// 默认的图片下载器 + (instancetype)imageLoader; /// 图片下载queue @property(nonatomic, strong, readonly) NSOperationQueue *downloadQueue; /// 图片下载顺序 @property(nonatomic, assign) STImageDownloadOrder downloadOrder; /** * @abstract 根据URLString 去下载图片,并且根据回调通知给调用方 * * @param URLString 图片的URL地址 * @param progressHandler 图片下载过程中,下载进度的回调.@see STImageProgressHandler * @param finishedHandler 图片下载完成的回调,会返回图片/错误 @see STImageLoaderHandler */ /// 以下两个方法为去服务端下载图片。 - (NSInteger)loadImageWithURLString:(NSString *)URLString finishedHandler:(STImageLoaderHandler)finishedHandler; - (NSInteger)loadImageWithURLString:(NSString *)URLString progressHandler:(STImageProgressHandler)progressHandler finishedHandler:(STImageLoaderHandler)finishedHandler; - (void)cancelLoadImageWithURLString:(NSString *)URLString; - (void)cancelLoadImageWithIdentifier:(NSInteger)identifier; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImagePickerController.h ================================================ // // STImagePickerController.h // STKit // // Created by SunJiangting on 14-1-3. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @class STImagePickerController; @protocol STImageProcessDelegate @optional - (NSData *)compressedOriginalImage:(UIImage *)originalImage; - (void)saveImageData:(NSData *)imageData withIdentifier:(NSString *)identifier; - (UIImage *)imageWithIdentifier:(NSString *)identifier; @end @protocol STImagePickerControllerDelegate @optional // The picker does not dismiss itself; the client dismisses it in these callbacks. // The delegate will receive one or the other, but not both, depending whether the user // confirms or cancels. - (void)imagePickerController:(STImagePickerController *)picker didFinishPickingImageWithInfo:(NSDictionary *)info; - (void)imagePickerControllerDidCancel:(STImagePickerController *)picker; @end @interface STImagePickerController : STNavigationController { // UIImagePickerController } - (instancetype)init NS_DESIGNATED_INITIALIZER; @property(nonatomic, copy) NSString *tips; @property(nonatomic) BOOL allowsMultipleSelection; /// 当相册load完之后,是否直接push进入第一个(全部照片) @property(nonatomic) BOOL wantsEnterFirstAlbumWhenLoaded; @property(nonatomic) NSInteger maximumNumberOfSelection; // default 20 @property(nonatomic) CGFloat maximumInteractivePopEdgeDistance; // default 13 @property(nonatomic, strong) UIButton *backBarButton; @property(nonatomic, strong) id userInfo; @property(nonatomic, weak) id delegate; @property(nonatomic, weak) id processDelegate; + (UIImage *)imageWithIdentifier:(NSString *)identifier; @end extern NSString *const STImagePickerControllerImageIdentifierKey; // a path of image in temp extern NSString *const STImagePickerControllerThumbImageKey; extern NSString *const STImagePickerControllerImageSizeKey; extern UIImage *STExactImageWithPath(); ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImagePresent.h ================================================ // // STImagePresent.h // STKit // // Created by SunJiangting on 14-9-21. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @protocol STImagePresentDelegate; @interface STImagePresent : NSObject /** * @abstract 展示imageView中的图片,查看大图。查看图片过程中,会使用动画从imageView所在的位置变换到大图界面。 * * @param imageView 需要展示的imageView。 */ + (void)presentImageView:(UIImageView *)imageView; + (void)presentImageView:(UIImageView *)imageView hdImage:(UIImage *)hdImage; + (void)presentImageView:(UIImageView *)imageView hdImageURL:(NSString *)hdImageURL; - (instancetype)initWithImages:(NSArray *)images; @property(nonatomic, weak) id delegate; - (void)presentImageAtIndex:(NSInteger)index animated:(BOOL)animated; @property(nonatomic, readonly) NSInteger presentedIndex; - (void)dismissAnimated:(BOOL)animated; @end @protocol STImagePresentDelegate @optional - (void)imagePresent:(STImagePresent *)imagePresent didPresentImageAtIndex:(NSInteger)index; - (UIImageView *)imagePresent:(STImagePresent *)imagePresent imageViewForImageAtIndex:(NSInteger)index; - (void)imagePresent:(STImagePresent *)imagePresent didLongPressImage:(UIImage *)image atIndex:(NSInteger)index; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageScrollView.h ================================================ // // STImageScrollView.h // STKit // // Created by SunJiangting on 13-12-25. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @class STImageScrollView, STRoundProgressView; @protocol STImageScrollViewDelegate @optional - (void)imageScrollViewDidTapped:(STImageScrollView *)imageScrollView; @optional - (void)imageScrollViewDidLongPressed:(STImageScrollView *)imageScrollView; @end @class STImageView; @interface STImageScrollView : UIScrollView @property(nonatomic, readonly, strong) UIImageView *imageView; @property(nonatomic, assign) BOOL autoFitImageView; @property(nonatomic, weak) id interactionDelegate; @property(nonatomic, strong, readonly) STRoundProgressView *roundProgressView; - (void)zoomToFit; - (void)zoomToFitImage:(UIImage *)image; - (void)setImage:(UIImage *)image animated:(BOOL)animated; - (void)setImageURL:(NSString *)imageURL animated:(BOOL)animated; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageView.h ================================================ // // STImageView.h // STKit // // Created by SunJiangting on 13-11-26. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import typedef enum STImageViewState { STImageViewStateNormal, STImageViewStateDownloadError, STImageViewStateDownloadFinished, } STImageViewState; @class STRoundProgressView; /// 支持GIF播放 @interface STImageView : UIImageView @property(nonatomic, readonly) STRoundProgressView *progressView; @property(nonatomic, copy) NSString *URLString; @property(nonatomic, assign) BOOL showProgressWhenLoading; @end /// 支持GIF播放的ImageView @interface STImageView (STGIFImage) /// GIF是否循环播放 @property (nonatomic, assign) BOOL repeats; /// 是否正在播放GIF @property (nonatomic, assign, readonly, getter=isPlaying) BOOL playing; @property (nonatomic, assign) BOOL automaticallyPlay; @property (nonatomic, strong) void (^completionHandler)(STImageView *imageView, BOOL finished); /// Default NSRunLoopCommonModes @property (nonatomic, strong) NSString *playInMode; - (void)play; - (void)pause; - (void)stop; - (void)replay; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STImageViewController.h ================================================ // // STImageViewController.h // STKit // // Created by SunJiangting on 13-12-25. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @class STImageViewController; @protocol STImageViewControllerDelegate @optional - (void)imageViewController:(STImageViewController *)imageViewController didScrollToImageAtIndex:(NSInteger)imageIndex; @end @interface STImageViewController : STViewController @property(nonatomic, weak) id delegate; @property(nonatomic, assign) NSInteger selectedIndex; /// 所有Image 数组 @property(nonatomic, copy) NSArray *imageDataSource; @property(nonatomic, copy) NSString *navigationTitle; /// 长按 是否存储到相册 @property(nonatomic, assign) BOOL saveImageToAlbumWhenLongPressed; @end // PS. 以下key为imageDataSource Key /// 预览图片缩略图 extern NSString *const STImagePreviewThumbImageKey; /// 预览图片缩略图 URL extern NSString *const STImagePreviewThumbImageURLKey; /// 预览图片大图 extern NSString *const STImagePreviewOriginalImageURLKey; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STIndicatorView.h ================================================ // // STIndicatorView.h // STKit // // Created by SunJiangting on 14-7-3. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import typedef NS_ENUM(NSInteger, STIndicatorType) { STIndicatorTypeCustom, STIndicatorTypeWaiting, STIndicatorTypeText }; ST_ASSUME_NONNULL_BEGIN @class STIndicatorView; @protocol STIndicatorViewDelegate @optional /** * @abstract 指示器被完全隐藏之后的回调, 一般会在hide之后动画结束了调用。参考minDisplayDuration * * @param indicatorView 隐藏的指示器 */ - (void)indicatorViewDidHidden:(STIndicatorView *)indicatorView; @end /** * @abstract 指示器。 */ @interface STIndicatorView : UIView /** * @abstract 显示指示器,指示器会被添加到view上,如果view = nil, 则添加到 keywindow上。 * * @param view 指示器需要显示的superview * @param animated 是否需要动画 */ + (instancetype)showInView:(STNULLABLE UIView *)view animated:(BOOL)animated; /// If window is nil, add to new window (level higher than statusBar) + (instancetype)showInWindow:(STNULLABLE UIWindow *)window animated:(BOOL)animated; /** * @abstract 关闭view上的所有指示器 * * @param view 需要关闭指示器的view * @param animated 关闭的时候是否需要动画 */ + (BOOL)hideInView:(STNULLABLE UIView *)view animated:(BOOL)animated; /** * @abstract 该view上的指示器, 如果该view上没有指示器,则返回nil * * @param view 有指示器的view。 */ + (STNULLABLE instancetype)indicatorInView:(STNULLABLE UIView *)view; + (STNULLABLE NSArray *)allIndicatorInView:(STNULLABLE UIView *)view; /** * @abstract default initializer * * @param view 该indicatorView会被添加到view上,如果view=nil,则为keywindow */ - (instancetype)initWithView:(STNULLABLE UIView *)view; /** * @abstract 显示/隐藏指示器。 * * @param animated 是否需要动画 */ - (void)showAnimated:(BOOL)animated; - (void)hideAnimated:(BOOL)animated; /// 延时隐藏指示器 - (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay; - (void)hideAnimated:(BOOL)animated afterDelay:(NSTimeInterval)delay completion:(STNULLABLE void (^)(void))completion; @property(nonatomic) STBlurEffectStyle blurEffectStyle; /// 指示器弧度,默认 10 @property(nonatomic) CGFloat cornerRadius; /// 指示器间距,default 0 0 @property(nonatomic) CGPoint contentOffset; /// default 20 @property(nonatomic) UIEdgeInsets contentInsets; /// 指示器最小为多大,默认 0 0 @property(nonatomic) CGSize minimumSize; /// 您可以添加默认的customView. 当mode为STIndicatorTypeCustom时 @property(STPROPERTYNULLABLE nonatomic, strong) UIView *customView; @property(nonatomic, weak) id delegate; @property(nonatomic) STIndicatorType indicatorType; @property(STPROPERTYNONNULL nonatomic, strong, readonly) UIView *backgroundView; @property(nonatomic, readonly, strong) UILabel *textLabel; @property(nonatomic, readonly, strong) UILabel *detailLabel; /// 是否强制为正方形。 默认NO @property(nonatomic, getter=isForceSquare) BOOL forceSquare; /// 当指示器不显示的时候是否将指示器移除 @property(nonatomic) BOOL removeWhenStopped; @property(nonatomic) CGFloat minimumDisplayDuration; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STJavaScriptBridge.h ================================================ // // STJavaScriptBridge.h // STKit // // Created by SunJiangting on 14-10-16. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @class STJavaScriptBridgeItem; typedef void (^STBridgeCompletionHandler)(NSDictionary *dictionary); typedef void (^STBridgeHandler)(STJavaScriptBridgeItem *item, STBridgeCompletionHandler completionHandler); @interface STJavaScriptBridgeItem : NSObject @property(nonatomic, copy) NSString *eventID; @property(nonatomic, copy) NSString *callbackID; @property(nonatomic, copy) NSString *method; @property(nonatomic, copy) NSDictionary *parameters; @end @interface STJavaScriptBridge : NSObject @property(nonatomic, weak, readonly) UIWebView *webview; @property(nonatomic, copy) NSString *scheme; @property(nonatomic, copy) NSString *host; - (void)registerBridgeHandler:(STBridgeHandler)bridgeHandler forJSMethod:(NSString *)JSMethod; @end @interface UIWebView (STJavaScriptBridge) @property(nonatomic, strong, readonly) STJavaScriptBridge *JSBridge; @property(nonatomic, assign) BOOL allowsJavaScriptBridge; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STKeychain.h ================================================ // // STKeychain.h // STKit // // Created by SunJiangting on 15/6/28. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import ST_ASSUME_NONNULL_BEGIN @interface STKeychain : NSObject - (id)initWithIdentifier:(STNULLABLE NSString *)identifier accessGroup:(STNULLABLE NSString *)accessGroup NS_DESIGNATED_INITIALIZER; - (void)setValue:(STNULLABLE id)value forKey:(NSString *)key; - (STNULLABLE id)valueForKey:(NSString *)key; - (void)removeAllValues; @end @interface STKeychainManager : NSObject + (instancetype)sharedManager; - (void)setValue:(STNULLABLE id)value forKey:(NSString *)key; - (STNULLABLE id)valueForKey:(NSString *)key; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STKit.h ================================================ // // STKit.h // STKit // // Created by SunJiangting on 13-11-20. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import // STKit+UIView #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import #import // STKit+ViewController #import #import #import #import #import #import #import #import #import #import #import // STKit+Network #import #import #import #import #import // STKit+Audio //#import #import #import #import // STKit+Persist #import #import #import // STKit + Layout #import // STKit+Theme #import #import #import // STKit+MVC #import #import #import #import // appcontext #import // Security #import #import #import #import #import ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STLabel.h ================================================ // // STLabel.h // STKit // // Created by SunJiangting on 13-10-26. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import typedef enum { STVerticalAlignmentTop, // default STVerticalAlignmentMiddle, STVerticalAlignmentBottom, } STVerticalAlignment; /** * @abstract 为Label添加垂直对齐方式和内容间距 */ @interface STLabel : UILabel /// 垂直方向上的对其方式 @property(nonatomic, assign) STVerticalAlignment verticalAlignment; /// 内容间距 @property(nonatomic, assign) UIEdgeInsets contentInsets; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STLinkLabel.h ================================================ // // STLinkLabel.h // STKit // // Created by SunJiangting on 13-11-27. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import /** * @abstract location是否被该Range包含 */ ST_INLINE BOOL STLocationInRange(NSRange range, NSUInteger location) { return (location >= range.location) && (location < (range.location + range.length)); } /** * @abstract range1 是否包含range2 */ ST_INLINE BOOL STRangeContainsRange(NSRange range1, NSRange range2) { BOOL startContains = (range2.location >= range1.location) && (range2.location <= (range1.location + range1.length)); BOOL endContains = ((range2.location + range2.length) >= range1.location) && ((range2.location + range2.length) <= (range1.location + range1.length)); return startContains && endContains; } /// 自定义Link标签display static u_int64_t STTextCheckingTypeCustomLink = (1ULL << 33); /** * @abstract 点击事件的对象,内包含URL,range。@see STLinkLabel, NSTextCheckingResult * 如果是STTextCheckingType, 则从value中去取值 */ @interface STLinkObject : NSObject /// 该对象包含的URL,如果没有URL @property(STPROPERTYNULLABLE nonatomic, readonly, strong) NSURL *URL; @property(STPROPERTYNULLABLE nonatomic, readonly, strong) NSString *value; @property(nonatomic, readonly, assign) NSRange range; @end ST_ASSUME_NONNULL_BEGIN @class STLinkLabel; /** * @abstract 超链接点击时的回调 * 普通Link http://a.b.c * CustomLink display */ @protocol STLinkLabelDelegate @optional /** * @abstract 超链接被点击的事件 * * @param linkLabel 点击事件的label * @param linkObject 点击到的超链接对象 */ - (void)linkLabel:(STLinkLabel *)linkLabel didSelectLinkObject:(STLinkObject *)linkObject; @optional /** * @abstract 超链接是否可以被点击 * * @param linkLabel 点击事件的label * @param linkObject 点击到的超链接对象 * @return YES 则会出发linkLabel:didSelectLinkObject: 回调 * */ - (BOOL)linkLabel:(STLinkLabel *)linkLabel shouldSelectLinkObject:(STLinkObject *)linkObject; @end ST_ASSUME_NONNULL_END /** * @abstract 此Label为可以带链接的Label。其中会自动解析文本中包含的链接 @see NSDataDetector, 并为其添加点击事件@see STLinkLabelDelegate。 * 支持CustomLink,格式为 display * 若要支持CustomLink,需要设置checkingType|STTextCheckingTypeCustomLink * CustomLink 优先于SystemTextCheckingType */ @interface STLinkLabel : UIView /// 是否自动解析超链接 @property(nonatomic, assign) BOOL autoHyperlink; /// 点击对象的事件委托 @property(STPROPERTYNULLABLE nonatomic, weak) id delegate; /// 文本内容 @property(STPROPERTYNULLABLE nonatomic, copy) NSString *text; /// 文本字体 @property(STPROPERTYNULLABLE nonatomic, strong) UIFont *font; /// 对其方式 default is NSTextAlignmentLeft @property(nonatomic, assign) NSTextAlignment textAlignment; /// 换行模式 default is NSLineBreakByWordWrapping @property(nonatomic, assign) NSLineBreakMode lineBreakMode; /// 暂时未用到 @property(nonatomic, assign) NSInteger numberOfLines; /// 文本颜色 @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *textColor; /// 超链接颜色, 默认blue @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *linkColor; /// 超链接背景颜色 @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *linkBackgroundColor; /// 文本高亮的颜色 @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *highlightedTextColor; /// 超链接高亮的颜色 @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *highlightedLinkColor; /// 超链接高亮时的背景颜色,默认gray @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *highlightedLinkBackgroundColor; @property(nonatomic, assign) BOOL continueTouchEvent; @property(nonatomic, assign, getter=isHighlighted) BOOL highlighted; // default is NO @property(nonatomic, assign) UIBaselineAdjustment baselineAdjustment; // default is UIBaselineAdjustmentAlignBaselines /// @see STTextCheckingTypeCustomLink @property(nonatomic, assign) NSTextCheckingTypes textCheckingTypes; // default is NSTextCheckingTypeLink @property(nonatomic, assign) CGFloat verticalTouchAreaFactor; // default is 1.0 + (CGSize)sizeWithText:(STNONNULL NSString *)linkText font:(STNONNULL UIFont *)font constrainedToSize:(CGSize)constrainedSize paragraphStyle:(STNULLABLE NSParagraphStyle *)paragraphStyle; + (CGSize)sizeWithText:(STNONNULL NSString *)linkText textCheckingTypes:(NSTextCheckingTypes)checkingTypes font:(STNONNULL UIFont *)font constrainedToSize:(CGSize)constrainedSize paragraphStyle:(STNULLABLE NSParagraphStyle *)paragraphStyle; @end @interface NSString (STLinkLabel) - (CGSize)sizeWithFont:(STNONNULL UIFont *)font constrainedToSize:(CGSize)constrainedSize paragraphStyle:(STNULLABLE NSParagraphStyle *)paragraphStyle; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STLocationManager.h ================================================ // // STLocationManager.h // STKit // // Created by SunJiangting on 14-5-13. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import typedef void (^STLocationHandler)(CLLocation *location, NSError *error); typedef void (^STGeoReverseHandler)(CLPlacemark *placemark, NSError *error); @interface STLocationManager : NSObject + (instancetype)sharedManager; - (void)requestWhenInUseAuthorization; - (void)requestAlwaysAuthorization; - (void)obtainLocationWithHandler:(STLocationHandler)handler; - (void)obtainLocationWithGeoHandler:(STGeoReverseHandler)geoReverseHandler; /// first step. obtain location then reverse geocode - (void)obtainLocationWithHandler:(STLocationHandler)handler reverseGeocodeHandler:(STGeoReverseHandler)geoReverseHandler; - (void)reverseLocation:(CLLocation *)location reverseHandler:(STGeoReverseHandler)geoReverseHandler; /// default nil, if has been located once, it will be the lastest location @property(atomic, strong) CLLocation *location; @property(atomic, strong) CLPlacemark *placemark; @property(nonatomic, strong) NSError *error; @end extern NSString *const STLocationDidObtainNotification; extern NSString *const STLocationDidReverseNotification; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STModel.h ================================================ // // STModel.h // STKit // // Created by SunJiangting on 13-12-17. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import "STHTTPOperation.h" /** * 数据加载的来源,包括从本地Cache加载,下拉刷新,分页获取更多等 */ typedef NS_ENUM(NSInteger, STModelDataSourceType) { STModelDataSourceTypeCache, STModelDataSourceTypeRemote, STModelDataSourceTypePagination, }; @class STModel; @protocol STModelDelegate - (void)modelWillStartLoadData:(STModel *)model; - (void)modelDidFinishLoadData:(STModel *)model; /// 当加载失败是,error不为nil。 - (void)modelDidFailedLoadData:(STModel *)model; /// 如果正在加载更多,但是又触发了下拉刷新,则取消加载更多 - (void)modelDidCancelLoadData:(STModel *)model; @optional - (void)model:(STModel *)model didInsertItemAtIndexPaths:(NSArray *)indexPaths; // if indexPaths == nil, preferred to reloadData - (void)model:(STModel *)model didReloadItemAtIndexPaths:(NSArray *)indexPaths; - (void)model:(STModel *)model didDeleteItemAtIndexPaths:(NSArray *)indexPaths; @end @interface STModel : NSObject /// 如果有更多,则展示 加载更多,否则,则为空 - (BOOL)hasNextPage; @property(nonatomic, weak) id delegate; @property(nonatomic, assign) STModelDataSourceType sourceType; @property(nonatomic, strong) NSError *error; /// 注意。 当pagination的时候去操作下拉刷新,会取消当前的pagination操作。每一次加载更多,需要生成一个新的Operation @property(nonatomic, weak) STHTTPOperation *paginationOperation; /// 每次加载完毕后,会调用此方法,判断是否需要显示空数据 - (NSInteger)numberOfDataItems; - (id)objectAtIndexPath:(NSIndexPath *)indexPath; /// 从Cache加载 - (void)loadDataFromCache; - (void)loadDataFromRemote; - (void)loadDataFromPagination; - (void)saveDataToCache; /// 清除缓存 - (void)invalidateData; /// when subclass finish network , must call these method - (void)requestDidFinishWithObject:(id)object; - (void)requestDidCancelWithObject:(id)object; - (void)requestDidFailedWithObject:(id)object error:(NSError *)error; - (void)insertItem:(id)item atIndexPath:(NSIndexPath *)indexPath; - (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath; - (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths; - (NSArray *)itemsAtIndexPaths:(NSArray *)indexPaths; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STModelViewController.h ================================================ // // STModelViewController.h // STKit // // Created by SunJiangting on 13-12-17. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @interface STModelViewController : STViewController /// 返回Model的类名 + (Class)modelClass; @property(nonatomic, strong) STModel *model; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STNavigationBar.h ================================================ // // STNavigationBar.h // STKit // // Created by SunJiangting on 14-2-18. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import ST_ASSUME_NONNULL_BEGIN @interface STNavigationBar : UIView @property(STPROPERTYNULLABLE nonatomic, copy) NSString *title; @property(STPROPERTYNULLABLE nonatomic, strong) UIView *leftBarView; @property(STPROPERTYNULLABLE nonatomic, strong) UIView *titleView; @property(STPROPERTYNULLABLE nonatomic, strong) UIView *rightBarView; @property(nonatomic, strong, readonly) UIView *transitionView; @property(STPROPERTYNULLABLE nonatomic, strong) UIImage *backgroundImage; @property(nonatomic, strong, readonly) UIView *separatorView; @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *barTintColor; @property(STPROPERTYNULLABLE nonatomic, copy) NSDictionary *titleTextAttributes; @property(nonatomic,assign,getter=isTranslucent) BOOL translucent; @end ST_ASSUME_NONNULL_END typedef NS_ENUM(NSInteger, STBarButtonCustomItem) { STBarButtonCustomItemBack, STBarButtonCustomItemDismiss, STBarButtonCustomItemMore, }; @interface UIBarButtonItem (STKit) + (STNULLABLE instancetype)backBarButtonItemWithTarget:(STNULLABLE id)target action:(STNULLABLE SEL)action; - (STNULLABLE instancetype)initWithBarButtonCustomItem:(STBarButtonCustomItem)customItem target:(STNULLABLE id)target action:(STNULLABLE SEL)action; - (STNULLABLE instancetype)initWithTitle:(STNULLABLE NSString *)title target:(STNULLABLE id)target action:(STNULLABLE SEL)action; - (STNULLABLE instancetype)initWithTitle:(STNULLABLE NSString *)title tintColor:(STNULLABLE UIColor *)tintColor target:(STNULLABLE id)target action:(STNULLABLE SEL)action; - (STNULLABLE UIView *)st_customView; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STNavigationController.h ================================================ // // STNavigationController.h // STKit // // Created by SunJiangting on 14-2-13. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import typedef NS_ENUM(NSInteger, STViewControllerTransitionType) { STViewControllerTransitionTypePush, STViewControllerTransitionTypePop, }; ST_ASSUME_NONNULL_BEGIN @interface STNavigationControllerTransitionContext : NSObject @property (nonatomic, readonly) UIViewController *fromViewController; @property (nonatomic, readonly) UIViewController *toViewController; // fromTransitionView 不一定是fromViewController.view。动画一定要在fromTransitionView上做. @property (nonatomic, readonly) UIView *fromView; @property (nonatomic, readonly) UIView *toView; // 动画完成的比例 @property (nonatomic, readonly) CGFloat completion; @property (nonatomic, readonly) STViewControllerTransitionType transitionType; @property (nonatomic, readonly) UIView *transitionView; //@property (nonatomic, readonly) BOOL transitionWithInteraction; @end ST_ASSUME_NONNULL_END /// UINavigationController @class STNavigationBar; @protocol STNavigationControllerDelegate; @interface STNavigationController : STViewController - (STNONNULL instancetype)initWithRootViewController:(UIViewController * ST_NULLABLE)rootViewController; // Convenience method pushes the root view controller without animation. - (void)pushViewController:(UIViewController * ST_NONNULL)viewController animated:(BOOL)animated; // Uses a horizontal slide transition. Has no effect if the view controller is already in the stack. - (UIViewController * ST_NULLABLE)popViewControllerAnimated:(BOOL)animated; // Returns the popped controller. - (NSArray * ST_NULLABLE)popToViewController:(UIViewController * ST_NONNULL)viewController animated:(BOOL)animated; // Pops view controllers until the one specified is on top. Returns the popped controllers. - (NSArray * ST_NULLABLE)popToRootViewControllerAnimated:(BOOL)animated; // Pops until there's only a single view controller left on the stack. Returns the popped controllers. @property(STPROPERTYNULLABLE nonatomic, readonly, strong) UIViewController *topViewController; // The top view controller on the stack. @property(STPROPERTYNULLABLE nonatomic, readonly, strong) UIViewController *visibleViewController; // Return modal view controller if it exists. Otherwise the top view controller. @property(STPROPERTYNULLABLE nonatomic, copy) NSArray *viewControllers; // The current view controller stack. - (void)setViewControllers:(NSArray<__kindof UIViewController *> * ST_NULLABLE)viewControllers animated:(BOOL)animated; // If animated is YES, then simulate a push or pop depending on whether the new top view controller was // previously in the stack. @property(STPROPERTYNONNULL nonatomic, readonly) STNavigationBar *navigationBar; // The navigation bar managed by the controller. Pushing, popping or setting navigation // items on a managed navigation bar is not supported. @property(STPROPERTYNULLABLE nonatomic, weak) id delegate; /// @property(STPROPERTYNONNULL nonatomic, readonly) UIGestureRecognizer *interactivePopGestureRecognizer; @property(STPROPERTYNONNULL nonatomic, strong, readonly) UIView *transitionView; @property(STPROPERTYNULLABLE nonatomic, strong, readonly) STShadow *shadow; @property(nonatomic) CGFloat maximumPopAnimationMaskAlpha; @end /// NavigationController Push/Pop时间 extern CGFloat const STTransitionViewControllerAnimationDuration; @interface UIViewController (STNavigationController) @property(nonatomic, setter=st_setNavigationBarHidden:) BOOL st_navigationBarHidden; @property(STPROPERTYNULLABLE nonatomic, readonly, strong) STNavigationBar *st_navigationBar; @property(STPROPERTYNULLABLE nonatomic, readonly, strong) STNavigationController *st_navigationController; /// @li 从最左侧开始生效返回手势,这个变量决定距离左侧多少可以激活手势,设置为0,则禁止左滑跟随返回 /// @li 有些套了手机壳的手机,壳边缘比较厚,设置比较小的话,影响操作,很难触发。 @property(nonatomic, setter=st_setMaximumInteractivePopEdgeDistance:) CGFloat st_maximumInteractivePopEdgeDistance; // 默认 30pt,系统默认13。 /// Pop/Push ViewController时,前一个ViewController's view的偏移量(iOS7的返回效果)。 /// 变量应该为Unsigned @property(nonatomic, setter=st_setInteractivePopTransitionOffset:) CGFloat st_interactivePopTransitionOffset; // default 80pt @end /// 30pt extern CGFloat const STMaximumInteractivePopEdgeDistance; /// 80pt extern CGFloat const STInteractivePopTransitionOffset; @protocol STNavigationControllerDelegate @optional /// 是否可以使用自定义的transition切换,如果返回False,则使用默认动画 - (BOOL)navigationController:(STNavigationController * ST_NONNULL)navigationController shouldBeginTransitionContext:(STNavigationControllerTransitionContext * ST_NONNULL)transitionContext; - (void)navigationController:(STNavigationController * ST_NONNULL)navigationController willBeginTransitionContext:(STNavigationControllerTransitionContext * ST_NONNULL)transitionContext; - (void)navigationController:(STNavigationController * ST_NONNULL)navigationController transitingWithContext:(STNavigationControllerTransitionContext * ST_NONNULL)transitionContext; - (void)navigationController:(STNavigationController * ST_NONNULL)navigationController didEndTransitionContext:(STNavigationControllerTransitionContext * ST_NONNULL)transitionContext; @end @interface UIViewController (STNavigationCallback) // This is a callback, do not need to call super - (void)st_didPopViewControllerAnimated:(BOOL)animated; @end @interface UIViewController (STNavigationScreenView) @property(STPROPERTYNULLABLE nonatomic, weak, readonly) UIView *st_superview; @end @interface UIViewController (STNavigationBarVisiblity) - (void)st_setNavigationBarHidden:(BOOL)st_navigationBarHidden animated:(BOOL)animated; - (void)st_setNavigationBarHidden:(BOOL)st_navigationBarHidden animated:(BOOL)animated alongWithAnimations:(nullable void(^)(void))animations; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STNetworkConfiguration.h ================================================ // // STNetworkConfiguration.h // STKit // // Created by SunJiangting on 14-10-18. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import "STHTTPConfiguration.h" /// 以下内容仅有一项就可以了 @interface STCertificateItem : NSObject /// cer 文件的路径 [NSData dataWithContentsOfFile:filePath] @property(nonatomic, copy) NSString *filePath; /// cer 文件base64编码之后的字符串 @property(nonatomic, copy) NSString *base64String; /// cer 文件内容 data @property(nonatomic, copy) NSData *data; /// + (instancetype)certificateItemWithFilePath:(NSString *)filePath; + (instancetype)certificateItemWithBase64String:(NSString *)base64String; + (instancetype)certificateItemWithData:(NSData *)data; @end typedef NS_ENUM(NSInteger, STSSLPinningMode) { STSSLPinningModeNone = 1 << 0, STSSLPinningModePublicKey = 1 << 1, // 只验证public是否正确 STSSLPinningModeCertificate = 1 << 2 // 验证Public是否正确,以及证书是否有效 }; @interface STNetworkConfiguration : NSObject + (instancetype)sharedConfiguration; /// 是否允许未经过验证的证书,默认允许。如果允许,则忽略SSLPinningMode。default yes @property BOOL allowsAnyHTTPSCertificate; /// 如果SSLMode 为publicKey,则需要指定publicKey或者指定certificates,实现会从certificates中读取到publickey,然后赋值给publicKey @property STSSLPinningMode SSLPinningMode; /// 如果你没有设置publicKeys,必要的时候(PinningMode==STSSLPinningModePublicKey)会从certificate中读取publicKey @property(nonatomic, copy) NSArray *publicKeys; /// 证书 目前只支持 cer格式。具体查看 @see STCertificateItem @property(nonatomic, copy) NSArray /**/ *certificates; @property(nonatomic, strong) NSURLCredential *HTTPBasicCredential; @property(nonatomic, strong) NSURLCredential *clientCertificateCredential; @property NSInteger cacheDiskCapacity; @property(nonatomic, strong) STHTTPConfiguration *HTTPConfiguration; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STNotificationWindow.h ================================================ // // STNotificationWindow.h // STKit // // Created by SunJiangting on 13-11-28. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import @protocol STNotificationWindowDelegate - (void)allNoticationViewDismissed; @end typedef void (^Completion)(BOOL completion); @class STNotificationWindow, STImageView, STLabel; ; @interface STNotificationView : UIView @property(nonatomic, strong, readonly) UIView *contentView; @property(nonatomic, readonly, strong) STImageView *imageView; @property(nonatomic, readonly, strong) STLabel *textLabel; @property(nonatomic, readonly, strong) STLabel *detailLabel; @property(nonatomic, strong, readonly) UIButton *closeButton; - (instancetype)initWithFrame:(CGRect)frame; /// do not use this initializer @end @interface STNotificationWindow : UIWindow @property(nonatomic, weak) id notificationWindowDelegate; /// max message the window can show. @property(nonatomic, assign) NSInteger maximumNumberOfWindows; @property(nonatomic, assign) NSTimeInterval displayDuration; - (void)pushNotificationView:(STNotificationView *)notificationView animated:(BOOL)animated; - (void)popNotificationViewAnimated:(BOOL)animated; @end @interface STNotificationCenter : NSObject @end @interface STNotificationWindow (STNotificationView) + (STNotificationView *)notificationViewWithInfo:(NSDictionary *)notificationInfo; @end extern NSString *const STNotificationViewImageNameKey; extern NSString *const STNotificationViewTitleTextKey; extern NSString *const STNotificationViewDetailTextKey; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STObject.h ================================================ // // STObject.h // STKit // // Created by SunJiangting on 14-8-30. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #ifdef ST_IMPLEMENTION_FILE #define ST_EXTERN #else #define ST_EXTERN extern #endif /** * @abstract 根据所传入的className和dictionary,构建一个Object * * @param objectClass 需要创建对象的ClassName。 * @param dictionary 需要构建的一系列参数 @see relationship * * @discussion 传入的不一定必须是STObject, 理论上任何类型都可以,但是必须有relationship方法的实现, relationship *不必列出所有的属性-key映射,只需要列出 属性和key不同的地方即可,如果全部相同,返回nil就可以, *也无需调用父类的relationship,key相同的relationship会覆盖父类的relationship。 */ ST_EXTERN id STObjectCreate(Class objectClass, NSDictionary *dictionary); /** * @abstract 将当前的对象属性映射到dictionary中。 */ ST_EXTERN NSDictionary *STObjectToDictionary(NSObject *object); /** * @abstract 为某个对象进行重新赋值 * * @discussion 传入的不一定必须是STObject, 理论上任何类型都可以, 将会把所有dictionary中未包含的值都置为空,剩下的都是用dictionary中的值 */ ST_EXTERN void STObjectResetValue(NSObject *object, NSDictionary *dictionary); /** * @abstract 更新Object中的某些字段的值 * * @discussion 注意,更新只是字典中包含的,就会取重新赋值,其余的不会改变. @see STObjectResetValue */ ST_EXTERN void STObjectUpdateValue(NSObject *object, NSDictionary *dictionary); /// Copy Object ST_EXTERN id STObjectCreateCopy(NSObject *object); /// 得到这个类下的所有属性关系映射 ST_EXTERN NSDictionary *STClassGetPropertyRelationship(Class class); /* @interface STTestObject : STObject @property(nonatomic, copy) NSString *name; @property(nonatomic, strong) STTestObject *friendObject; @property(nonatomic, copy) NSArray *otherObjects; @property(nonatomic, copy) NSArray *descriptions; @end @implementation STTestObject + (Class)otherObjectsClass { return [STTestObject class]; } + (Class)descriptionsClass { return [NSString class]; } @end // use dictionary @{@"name":@"name", @"friendObject":@{@"name":@"xxx", ...}, @"otherObjects":@[@{@"name":@"name", ...}, @"descriptions":@[@"description1", @"description2", ...]]} */ /** * @abstract 根据Dictionary自动对象映射。 * 目前可以根据dictionary为对应的变量赋值,集合类的仅支持NSArray/NSSet 以及NSMutable__##__, 不支持的部分,将保留原数据。 * * @discussion 注意,如果对象中包含数组,比如
*
\@property(nonatomic, copy) NSArray * friends; // class STFriend; * 则需要实现名称为propertyNameClass的类方法,用于将property数组解析成对应的对象数组 如果未实现类方法,则array会保持原始dictionary中的数据 */ @interface STObject : NSObject + (instancetype)objectWithDictionary:(NSDictionary *)dictionary; - (instancetype)initWithDictionary:(NSDictionary *)dictionary; /** * @abstract 根据dict更新Object中对应的属性 * * @param dictionary 需要更新的字段值,需要与relationship对应。 */ - (void)updateValueWithDictionary:(NSDictionary *)dictionary; /** * @abstract 重置Object变量值,如果字段没有传值,则初始化为原始值,比如 0 nil 等 * * @param dictionary 字段对应的值,需要与relationship对应。 */ - (void)resetValueWithDictionary:(NSDictionary *)dictionary; - (NSDictionary *)toDictionary; /** * @abstract relationship 为 property ---> dictionary key的对应。 * * @discussion 默认会有 propertyName ---> key的对应。 * 每个子类只需要写出与dictionary key不一样的那一部分而已,不需要super。 * 假设 ClassA 中 有 property a, dictionary中key也是a,则不需要重写此方法 * ClassB继承ClassA, ClassB中新增了变量b, 对应的是c,则需要重写此方法 relationship {return @{@"b":@"c"}}, 只返回不一样的对应即可 * * @attention dictionary的key为property, value 为dict's key */ + (NSDictionary *)relationship; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STPaginationControl.h ================================================ // // STPaginationControl.h // STKit // // Created by SunJiangting on 14-9-17. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import /// 分页空间,列表滑动到最底部时,请求加载下一页。加载更多 @interface STPaginationControl : UIControl /// 距离底部多少开始触发分页操作 @property(nonatomic, assign) CGFloat threshold; /// 是否正在加载更多 @property(nonatomic, readonly, getter=isLoading) BOOL loading; @property(nonatomic, assign) STPaginationControlState paginationState; - (void)paginationControlDidChangedToState:(STPaginationControlState)controlState; /// 尝试去触发LoadMore(如果条件允许的话) - (void)paginationTest; @end @interface STDefaultPaginationControl : STPaginationControl @property(nonatomic, strong) UIButton *reloadButton; @property(nonatomic, strong) UILabel *titleLabel; @property(nonatomic, strong) UIActivityIndicatorView *indicatorView; - (void)setTitle:(NSString *)title forState:(STPaginationControlState)state; - (NSString *)titleForState:(STPaginationControlState)state; @end extern CGSize const STPaginationControlSize; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STPayManager.h ================================================ // // STPayManager.h // STKit // // Created by SunJiangting on 14-9-3. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import typedef NS_ENUM(NSInteger, STPayResult) { STPayResultSuccess, STPayResultCancelled, STPayResultError, }; typedef NS_OPTIONS(NSUInteger, STPayPlatform){ STPayPlatformAliPay = 1 << 0, STPayPlatformWXPay = 1 << 1, STPayPlatformAll = (STPayPlatformAliPay | STPayPlatformWXPay), }; @class STPayManager, STPayItem; typedef void (^STPayHandler)(STPayItem *payItem, STPayResult result, NSError *error); @interface STPayItem : NSObject @property(nonatomic, copy) NSString *name; @property(nonatomic, copy) NSString *title; @property(nonatomic, assign) NSString *desc; @property(nonatomic, assign) NSString *detail; @property(nonatomic, assign) NSInteger count; /// 精确到分 @property(nonatomic, assign) CGFloat price; @property(nonatomic, assign) CGFloat amount; /// 可选参数 @property(nonatomic, assign) STPayPlatform defaultPlatform; @property(nonatomic, assign) STPayPlatform supportedPlatforms; - (instancetype)initWithDictionary:(NSDictionary *)dictionary; @end /// 有关第三方付款 @interface STPayManager : NSObject + (instancetype)sharedPayManager; - (BOOL)payForItem:(STPayItem *)payItem finishHandler:(STPayHandler)handler; - (void)cancelPayForItem:(STPayItem *)payItem; - (BOOL)canOpenURL:(NSURL *)URL; - (BOOL)openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; @end /// 支持的参数 stkit://pay?name=123&title=1234&detail=1234&price=4000&count=1&amount=4000&allowsEditing=1&platforms=3#1 extern BOOL STPayManagerOpenURL(NSURL *URL); extern BOOL STPayManagerCanOpenURL(NSURL *URL); ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STPayViewController.h ================================================ // // STPayViewController.h // STKit // // Created by SunJiangting on 14-9-3. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import "STPayManager.h" @interface STPayViewController : STViewController - (instancetype)initWithPayItem:(STPayItem *)payItem handler:(STPayHandler)payHandler; @property(nonatomic, readonly) STPayPlatform payPlatforms; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STPersistence.h ================================================ // // STPersistence.h // STKit // // Created by SunJiangting on 13-12-8. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import typedef NS_ENUM(NSInteger, STPersistenceDirectory) { STPersistenceDirectoryDocument, // document 目录 STPersistenceDirectoryLibiary, // Libiary 目录 STPersistenceDirectoryCache, // Cache 目录 STPersistenceDirectoryTemporary, // 临时目录 }; ST_ASSUME_NONNULL_BEGIN extern NSString *STPersistDocumentDirectory(); extern NSString *STPersistLibiaryDirectory(); extern NSString *STPersistCacheDirectory(); extern NSString *STPersistTemporyDirectory(); @interface STPersistence : NSObject - (instancetype)initWithDirectory:(STPersistenceDirectory)directory subpath:(STNULLABLE NSString *)subpath; - (void)setValue:(STNULLABLE id)value forKey:(NSString *)key; - (STNULLABLE id)valueForKey:(NSString *)key; - (BOOL)containsValueForKey:(NSString *)key; - (STNONNULL NSString *)cacheDirectory; - (NSString *)cachedPathForKey:(NSString *)key; @end /// 通过以下方法创建的都会都会根据name来创建name.plist.相同name会被存储到单独的文件中 @interface STPersistence (STFileBased) + (instancetype)standardPersistence; + (instancetype)persistenceNamed:(STNULLABLE NSString *)name; @end @interface STPersistence (STPersistCreation) + (instancetype)documentPersistence; + (instancetype)libiaryPersistence; + (instancetype)tempoaryPersistence; + (instancetype)cachePersistence; + (instancetype)documentPersistenceWithSubpath:(STNULLABLE NSString *)subpath; + (instancetype)libiaryPersistenceWithSubpath:(STNULLABLE NSString *)subpath; + (instancetype)cachePersistenceWithSubpath:(STNULLABLE NSString *)subpath; + (instancetype)tempoaryPersistenceWithSubpath:(STNULLABLE NSString *)subpath; @end @interface STPersistence (STPersistenceClean) - (unsigned long long)cachedSize; - (void)calculateCacheSizeWithCompletionHandler:(void(^)(unsigned long long))completionHandler; - (void)calculateCacheSizeInQueue:(STNULLABLE dispatch_queue_t)backgroundQueue completionHandler:(void(^)(unsigned long long))completionHandler; /// 这个对 persistenceNamed的无效, persistenceNamed的需要使用reset/removeAllCachedValues来清空 - (void)removeCachedValuesBeforeDate:(STNULLABLE NSDate *)date; /// - (void)removeAllCachedValues; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STPopoverView.h ================================================ // // STPopoverView.h // STKit // // Created by SunJiangting on 14-5-23. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import /// attention: 这个方向是表示朝向,比如Up就表示从下往上弹出。 typedef NS_ENUM(NSInteger, STPopoverViewDirection) { STPopoverViewDirectionUp, STPopoverViewDirectionDown, STPopoverViewDirectionLeft, STPopoverViewDirectionRight, }; @protocol STPopoverViewDelegate; @interface STPopoverView : UIView /// all subview must be add to the contentView @property(nonatomic, strong, readonly) UIView *contentView; /// the contentoffset from it's parentView . see showInview can get the parentview @property(nonatomic, assign) CGPoint contentOffset; /// now visible @property(nonatomic, assign, readonly) BOOL visible; /// this direction is the direction how it's popfrom @property(nonatomic, assign) STPopoverViewDirection direction; - (void)showInView:(UIView *)view animated:(BOOL)animated; /* Called to dismiss the popover programmatically. The delegate methods for "should" and "did" dismiss are not called when the popover is dismissed in * this way. */ - (void)dismissAnimated:(BOOL)animated; /// background mask, default black alpha 0.5. the alpha will change when animated @property(nonatomic, strong, readonly) UIView *backgroundView; @property(nonatomic, weak) id delegate; @end @protocol STPopoverViewDelegate @optional - (BOOL)popoverViewShouldDismiss:(STPopoverView *)popoverView; - (void)popoverViewDidDismiss:(STPopoverView *)popoverView; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STRSACryptor.h ================================================ // // STRSACryptor.h // STKit // // Created by SunJiangting on 14-9-19. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import /** * @abstract 根据格式,从Data中读取公钥/私钥 * * @param data 密钥的data * @param base64String 密钥经过base64编码之后的数据 * @return 密钥(autorelease) */ extern SecKeyRef STSecPublicKeyFromDERData(NSData *data); extern SecKeyRef STSecPublicKeyFromDERBase64String(NSString *base64String); extern SecKeyRef STSecPublicKeyFromPEMData(NSData *data); extern SecKeyRef STSecPublicKeyFromPEMBase64String(NSString *base64String); extern SecKeyRef STSecPrivateKeyFromPEMData(NSData *data); extern SecKeyRef STSecPrivateKeyFromPEMBase64String(NSString *base64String); /// 目前只支持有密码的P12文件读取,如果没有密码的,iOS库本身不支持 extern SecKeyRef STSecPrivateKeyFromP12Data(NSData *data, NSString *password); /// 比较两个key是否相同 extern BOOL STSecKeyEqualToSecKey(SecKeyRef key1, SecKeyRef key2); @interface STRSACryptor : NSObject - (instancetype)initWithPublicSecKey:(SecKeyRef)publicSecKey privateSecKey:(SecKeyRef)privateSecKey; @property(nonatomic, readonly) NSInteger padding; /** * @abstract 使用私钥对data进行签名 * * @param data 需要签名的数据 * @return 返回签名后的数据 */ - (NSData *)signData:(NSData *)data; /** * @abstract 使用公钥验证签名是否有效 * * @param signature 使用私钥签名之后的数据 * @param signedData 原始 未被签名的数据 * @return 是否验证通过 */ - (BOOL)verifySignature:(NSData *)signature signedData:(NSData *)signedData; /// 使用公钥加密/私钥解密 data : 需要加/解密的数据 - (NSData *)encryptData:(NSData *)data; - (NSData *)decryptData:(NSData *)data; @end extern NSString *const STSecAttrApplicationTag; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STRateControl.h ================================================ // // STRateControl.h // STKit // // Created by SunJiangting on 14-9-18. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import /// 几颗星 打分组件 @interface STRateControl : UIControl //- (instancetype) initWithStaredImage:(UIImage *) staredImage unstaredImage:(UIImage *) unstaredImage; /// 填充满的星星 @property(nonatomic, strong) UIImage *staredImage; /// 未填充满的星星 @property(nonatomic, strong) UIImage *unstaredImage; /// 每个星星之间的间隔 @property(nonatomic, assign) CGFloat verticalMargin; /// 最多的value, 默认 5 @property(nonatomic, assign) CGFloat maximumValue; /// 当前value @property(nonatomic, assign) CGFloat value; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STReachability.h ================================================ // // STReachability.h // STKit // // Created by SunJiangting on 13-12-7. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import typedef NS_ENUM(NSInteger, STNetworkStatus) { STNetworkStatusReachNone, // 网络不通 STNetworkStatusReachWIFI, // WIFI STNetworkStatusReachWWAN, // GPRS,E等 }; /** * @abstract 此类可以获取网络的一些状况 */ @interface STReachability : NSObject + (instancetype)defaultReachability; /// 是否能够ping通host + (instancetype)reachabilityWithHost:(NSString *)host; /// designed initializer - (instancetype)initWithHost:(NSString *)host; - (STNetworkStatus)reachabilityStatus; - (SCNetworkReachabilityFlags)reachabilityFlags; @end @interface STReachability (STNotification) /** * @abstract 开启/关闭网络状态改变的通知 @see *STReachabilityDidChangedNotification * * @discussion 该通知肯定在主线程发送。 */ - (BOOL)startNotification; - (void)stopNotification; @end @interface STReachability (STAccessor) - (BOOL)reachable; - (BOOL)reachWWAN; - (BOOL)reachWIFI; @end extern BOOL STIsNetworkConnected(); extern BOOL STIsWIFIConnected(); extern NSString *const STReachabilityDidChangedNotification; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STRefreshControl.h ================================================ // // STRefreshControl.h // STKit // // Created by SunJiangting on 14-9-17. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import /// 刷新控件 @interface STRefreshControl : UIControl /// 当scrollView.contentOffset 超过这个值时,会触发刷新事件 @property(nonatomic, assign) CGFloat threshold; /// 是否正在刷新 @property(nonatomic, readonly, getter=isRefreshing) BOOL refreshing; - (void)beginRefreshing; - (void)endRefreshing; /// 下拉刷新组件当前状态 @property(nonatomic, assign, readonly) STRefreshControlState refreshControlState; /// these are callback functions, do not call this method directly, if you want /// to custom your refreshcontrol, you should override them to fit different /// state. - (void)scrollViewDidChangeContentOffset:(CGPoint)contentOffset; - (void)refreshControlWillChangedToState:(STRefreshControlState)refreshControlState; - (void)refreshControlDidChangedToState:(STRefreshControlState)refreshControlState; @property(nonatomic, assign) NSTimeInterval animationDuration; /// 最短的加载时间 @property(nonatomic, assign) NSTimeInterval minimumLoadingDuration; @end @interface STDefaultRefreshControl : STRefreshControl // 内部的控件 @property(nonatomic, weak) UILabel *refreshStatusLabel; @property(nonatomic, weak) UIImageView *arrowImageView; @property(nonatomic, weak) UIActivityIndicatorView *indicatorView; - (void)setTitle:(NSString *)title forState:(STRefreshControlState)state; - (NSString *)titleForState:(STRefreshControlState)state; @end extern CGSize const STRefreshControlSize; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STRoundProgressView.h ================================================ // // STRoundProgressView.h // STKit // // Created by SunJiangting on 13-11-26. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import /** * @abstract 环形的进度完成率,默认风格为iOS7 应用下载的风格. */ @interface STRoundProgressView : UIControl /// 完成度 @property(nonatomic) CGFloat completion; - (void)setCompletion:(CGFloat)completion animated:(BOOL)animated; @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *progressTintColor; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STScrollDirector.h ================================================ // // STScrollDirector.h // STKit // // Created by SunJiangting on 14-5-10. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import #import @interface STAccessoryView : UIView @property(nonatomic, strong) UIImageView *imageView; @property(nonatomic, strong) UILabel *textLabel; @property(nonatomic, strong) UIButton *reloadButton; @end extern CGSize const STAccessoryViewMinimumSize; /// 可以为scrollView添加下拉刷新和分页加载更多。 @interface STScrollDirector : NSObject /// 主要提供set方法。。 @property(nonatomic, strong) UIScrollView *scrollView; @property(nonatomic, strong) STRefreshControl *refreshControl; @property(nonatomic, strong) STPaginationControl *paginationControl; @end @interface STScrollDirector (STDefaultControl) /// @see STRefreshControlState @see STPaginationControlState - (void)setTitle:(NSString *)title forState:(STScrollDirectorState)state; - (NSString *)titleForState:(NSInteger)state; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STSearchBar.h ================================================ // // STSearchBar.h // STKit // // Created by SunJiangting on 14-9-4. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STSearchEditView : UIView @property(nonatomic, strong) UIButton *deleteButton; @property(nonatomic, strong) UITextField *editTextField; @property(nonatomic, strong) UIImageView *backgroundImageView; - (void)reloadInputState; @end @protocol STSearchBarDelegate; @interface STSearchBar : UIView /// UISearchBar @property(nonatomic, readonly, strong) UIImageView *backgroundImageView; @property(nonatomic, readonly, strong) STSearchEditView *searchEditView; @property(nonatomic, copy) NSString *text; // current/starting search text @property(nonatomic, readonly, strong) UIButton *cancelView; /// default is nil. @property(nonatomic, readonly, strong) UIButton *leftButton; @property(nonatomic, readonly, strong) UIButton *rightButton; - (void)setEditing:(BOOL)editing animated:(BOOL)animated completion:(void (^)(BOOL))completion; @property(nonatomic, weak) id delegate; @end @protocol STSearchBarDelegate /// UISearchBar @optional - (BOOL)searchBarShouldBeginEditing:(STSearchBar *)searchBar; // return NO to not become first responder - (void)searchBarTextDidBeginEditing:(STSearchBar *)searchBar; // called when text starts editing - (BOOL)searchBarShouldEndEditing:(STSearchBar *)searchBar; // return NO to not resign first responder - (void)searchBarTextDidEndEditing:(STSearchBar *)searchBar; // called when text ends editing - (void)searchBar:(STSearchBar *)searchBar textDidChange:(NSString *)searchText; // called when text changes (including clear) - (BOOL)searchBar:(STSearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // called before text changes - (void)searchBarSearchButtonClicked:(STSearchBar *)searchBar; // called when keyboard search button pressed - (void)searchBarBookmarkButtonClicked:(STSearchBar *)searchBar; // called when bookmark button pressed - (void)searchBarCancelButtonClicked:(STSearchBar *)searchBar; // called when cancel button pressed - (void)searchBarResultsListButtonClicked:(STSearchBar *)searchBar; // called when search results button pressed - (void)searchBar:(STSearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope; @end extern CGFloat const STSearchViewDefaultHeight; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STSearchDisplayController.h ================================================ // // STSearchDisplayController.h // STKit // // Created by SunJiangting on 14-9-4. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import "STSearchBar.h" @protocol STSearchDisplayDelegate; @interface STSearchDisplayController : NSObject /// UISearchDisplayController - (instancetype)initWithSearchBar:(STSearchBar *)searchView contentsController:(UIViewController *)viewController; @property(nonatomic, weak) id delegate; @property(nonatomic, getter=isActive) BOOL active; // configure the view controller for searching. default is NO. // animated is NO - (void)setActive:(BOOL)visible animated:(BOOL)animated; // animate the view controller for searching @property(nonatomic, readonly, weak) STSearchBar *searchBar; @property(nonatomic, readonly, weak) UIViewController *searchContentsController; // the view we are searching (often a UITableViewController) @property(nonatomic, readonly) UITableView *searchResultsTableView; // will return non-nil. create if requested @property(nonatomic, weak) id searchResultsDataSource; // default is nil. delegate can provide @property(nonatomic, weak) id searchResultsDelegate; // default is nil. delegate can provide @property(nonatomic, copy) NSString *searchResultsTitle; // default is nil. If nil, the controller uses the default title string @end @protocol STSearchDisplayDelegate @optional // when we start/end showing the search UI - (void)searchDisplayControllerWillBeginSearch:(STSearchDisplayController *)controller; - (void)searchDisplayControllerDidBeginSearch:(STSearchDisplayController *)controller; - (void)searchDisplayControllerWillEndSearch:(STSearchDisplayController *)controller; - (void)searchDisplayControllerDidEndSearch:(STSearchDisplayController *)controller; // called when table is shown/hidden - (void)searchDisplayController:(STSearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView; - (void)searchDisplayController:(STSearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView; - (void)searchDisplayController:(STSearchDisplayController *)controller willHideSearchResultsTableView:(UITableView *)tableView; - (void)searchDisplayController:(STSearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView; // return YES to reload table. called when search string/option changes. // convenience methods on top UISearchBar delegate methods - (BOOL)searchDisplayController:(STSearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString; - (BOOL)searchDisplayController:(STSearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STShadow.h ================================================ // // STShadow.h // STKit // // Created by SunJiangting on 15/8/27. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import ST_ASSUME_NONNULL_BEGIN @interface STShadow : NSObject @property(nonatomic, copy) UIColor *shadowColor; /* The opacity of the shadow. Defaults to 0. Specifying a value outside the * [0,1] range will give undefined results. Animatable. */ @property(nonatomic) CGFloat shadowOpacity; /* The shadow offset. Defaults to (0, -3). Animatable. */ @property(nonatomic) CGSize shadowOffset; /* The blur radius used to create the shadow. Defaults to 3. Animatable. */ @property(nonatomic) CGFloat shadowRadius; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STSideBarController.h ================================================ // // STSideBarController.h // STKit // // Created by SunJiangting on 13-11-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import #import //// 侧滑生效的范围 /** * @abstract 侧滑导航在哪些区域通过左滑手势可以打开 * * @attention 默认从最左端可以产生侧滑效果。 */ typedef NS_ENUM(NSInteger, STSideInteractiveArea) { STSideInteractiveAreaNone = 0,// 无任何侧滑效果 STSideInteractiveAreaNavigationBar = 1 << 0,// 导航条可以通过手势侧滑 STSideInteractiveAreaContentView = 1 << 1,// 中间区域可以通过手势侧滑 STSideInteractiveAreaAll = (STSideInteractiveAreaNavigationBar | STSideInteractiveAreaContentView) }; ST_ASSUME_NONNULL_BEGIN @interface STSideBarController : STViewController - (instancetype)initWithRootViewController:(UIViewController *)rootViewController NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(STNULLABLE NSString *)nibNameOrNil bundle:(STNULLABLE NSBundle *)nibBundleOrNil NS_DEPRECATED_IOS(2_0, 2_0, "Please use initWithRootViewController:"); /// sideBar 的最大宽度 @property(nonatomic) CGFloat maxSideWidth; /// 左侧阴影的Layer @property(nonatomic, strong, readonly) STShadow *shadow; @property(STPROPERTYNULLABLE nonatomic, copy) NSArray *viewControllers; - (void)setViewControllers:(STNULLABLE NSArray *)viewControllers animated:(BOOL)animated; /// 当前选中的ViewController @property(STPROPERTYNULLABLE nonatomic, readonly, weak) UIViewController *selectedViewController; @property(nonatomic) NSUInteger selectedIndex; /// sidebar 是否在可见区域,当侧边栏出现时sideAppeared = YES @property(nonatomic) BOOL sideAppeared; /// 滑动手势 @property(nonatomic, strong, readonly) UIPanGestureRecognizer *panGestureRecognizer; /** * @abstract 打开/关闭侧边栏,重复打开,则无效. * * @param animated 是否需要动画 */ - (void)revealSideViewControllerAnimated:(BOOL)animated; - (void)concealSideViewControllerAnimated:(BOOL)animated; /// 从最左侧抢占手势 @property(nonatomic) BOOL supportsEdgeInteractive; @end @interface UIViewController (SideBarController) @property(STPROPERTYNULLABLE nonatomic, readonly, weak) STSideBarController *st_sideBarController; @property(nonatomic, setter=st_setSideInteractionArea:) STSideInteractiveArea st_sideInteractionArea; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STStringTokenizer.h ================================================ // // STStringTokenizer.h // STKit // // Created by SunJiangting on 14-5-12. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import /// Text /// :后面的为 default value. /// to be continue /// 123.png @interface STStringTokenizer : NSObject + (NSAttributedString *)attributedStringWithMarkedString:(NSString *)markedText; /// 分词 + (NSDictionary *)dictionaryWithMarkedString:(NSString *)markedString; @end @interface UILabel (STStringTokenizer) - (void)setMarkedText:(NSString *)markedText; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTabBar.h ================================================ // // STTabBar.h // STKit // // Created by SunJiangting on 14-2-13. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @protocol STTabBarDelegate; @class STTabBarItem; /// UITabBar @interface STTabBar : UIView @property(STPROPERTYNULLABLE nonatomic, assign) id delegate; // weak reference. default is nil @property(STPROPERTYNULLABLE nonatomic, copy) NSArray *items; // get/set visible UITabBarItems. default is nil. changes not animated. shown in order @property(STPROPERTYNULLABLE nonatomic, assign) STTabBarItem *selectedItem; // will show feedback based on mode. default is nil /* The behavior of tintColor for bars has changed on iOS 7.0. It no longer affects the bar's background and behaves as described for the tintColor property added to UIView. To tint the bar's background, please use -barTintColor. */ @property(STPROPERTYNULLABLE nonatomic, retain) UIColor *barTintColor; // default is nil /* selectedImageTintColor will be applied to the gradient image used when creating the selected image. Default is nil and will result in the system bright blue for selected tab item images. If you wish to also customize the unselected image appearance, you must use -setFinishedSelectedImage:finishedUnselectedImage: on individual tab bar items. */ @property(STPROPERTYNULLABLE nonatomic, retain) UIColor *selectedImageTintColor; /* The background image will be tiled to fit, even if it was not created via the UIImage resizableImage methods. */ @property(STPROPERTYNULLABLE nonatomic, retain) UIImage *backgroundImage; @property(nonatomic, getter=isTranslucent) BOOL translucent; /// default NO, if YES you need to custom add subview @property(nonatomic, assign) BOOL customizable; - (void)setBadgeValue:(STNULLABLE NSString *)badgeValue forIndex:(NSInteger)index; - (STNULLABLE NSString *)badgeValueForIndex:(NSInteger)index; @property(STPROPERTYNONNULL nonatomic, strong, readonly) UIView *separatorView; @end ST_ASSUME_NONNULL_BEGIN @protocol STTabBarDelegate @optional - (void)tabBar:(STTabBar *)tabBar didSelectItem:(STTabBarItem *)item; // called when a new view is selected by the user (but not programatically) @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTabBarController.h ================================================ // // STTabBarController.h // STKit // // Created by SunJiangting on 14-2-13. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import @protocol STTabBarControllerDelegate; @class STTabBar, STTabBarItem; IB_DESIGNABLE ST_ASSUME_NONNULL_BEGIN @interface STTabBarController : STViewController @property(nonatomic, readonly, strong) UIView *transitionView; @property(nonatomic) BOOL animatedWhenTransition; @property(STPROPERTYNULLABLE nonatomic, copy)NSArray *viewControllers; // If the number of view controllers is greater than the number displayable by a tab bar, a "More" navigation controller will automatically be shown. // The "More" navigation controller will not be returned by -viewControllers, but it may be returned by -selectedViewController. - (void)setViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers animated:(BOOL)animated; @property(STPROPERTYNULLABLE nonatomic, weak) UIViewController *selectedViewController; @property(nonatomic) NSUInteger selectedIndex; @property(nonatomic, readonly) STTabBar *tabBar; @property(STPROPERTYNULLABLE nonatomic, weak) id delegate; /// default 49 @property(nonatomic, assign) CGFloat tabBarHeight; @property(nonatomic, assign) CGFloat actualTabBarHeight; - (void)setBadgeValue:(STNULLABLE NSString *)badgeValue forIndex:(NSInteger)index; - (STNULLABLE NSString *)badgeValueForIndex:(NSInteger)index; //- (void)setTabBarHidden:(BOOL)hidden animated:(BOOL)animated; @end ST_ASSUME_NONNULL_END @interface UIViewController (STTabBarControllerItem) // Automatically created lazily with the view controller's title if it's not set explicitly. @property(STPROPERTYNONNULL nonatomic, strong, setter=st_setTabBarItem:) STTabBarItem *st_tabBarItem; // If the view controller has a tab bar controller as its ancestor, return it. Returns nil otherwise. @property(STPROPERTYNULLABLE nonatomic, readonly, strong) STTabBarController *st_tabBarController; @end ST_ASSUME_NONNULL_BEGIN @protocol STTabBarControllerDelegate @optional - (BOOL)tabBarController:(STTabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController; - (void)tabBarController:(STTabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController; @end ST_ASSUME_NONNULL_END /// Default 49 extern const CGFloat STCustomTabBarHeight; ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTabBarItem.h ================================================ // // STTabBarItem.h // STKit // // Created by SunJiangting on 14-2-13. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import @interface STTabBarItem : NSObject @property(STPROPERTYNULLABLE nonatomic, copy) NSString *title; @property(STPROPERTYNULLABLE nonatomic, strong) UIImage *image; @property(STPROPERTYNULLABLE nonatomic, strong) UIImage *selectedImage; @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *titleColor; @property(STPROPERTYNULLABLE nonatomic, strong) UIColor *selectedTitleColor; @property(STPROPERTYNULLABLE nonatomic, strong) UIFont *titleFont; @property(STPROPERTYNULLABLE nonatomic, copy) NSString *badgeValue; @property(nonatomic, assign) CGRect imageFrame; @property(nonatomic, assign) CGRect titleFrame; @property(STPROPERTYNULLABLE nonatomic, weak) UIView *itemView; /// UITabBarItem - (STNONNULL instancetype)initWithTitle:(STNULLABLE NSString *)title image:(STNULLABLE UIImage *)image selectedImage:(STNULLABLE UIImage *)selectedImage; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTableView.h ================================================ // // STTableView.h // STKit // // Created by SunJiangting on 14-5-14. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STTableView : UITableView //// 该TableView是为了兼容iOS6.0以下 - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTableViewCell.h ================================================ // // STTableViewCell.h // STKit // // Created by SunJiangting on 15-1-19. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STTableViewCell : UITableViewCell @property(nonatomic, strong) UIColor *selectedBackgroundColor; @property(nonatomic, strong) UIColor *backgroundColor; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTableViewController.h ================================================ // // STTableViewController.h // STKit // // Created by SunJiangting on 14-5-14. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import #import @interface STTableViewController : STModelViewController @property(nonatomic, strong, readonly) UITableView *tableView; /// addtarget to receive refresh callback @property(nonatomic, weak, readonly) STRefreshControl *refreshControl; @property(nonatomic, weak, readonly) STPaginationControl *paginationControl; /// designed initializer - (instancetype)initWithStyle:(UITableViewStyle)style NS_DESIGNATED_INITIALIZER; //// 触发刷新方法 - (void)refreshData; - (void)refreshDataUsingRefreshControl; //// 当数据加载完成之后,会调用此方法,子类需重写,刷新列表等 - (void)reloadData; /// 当出现异常失败时,是否列表可以滚动 @property(nonatomic, assign) BOOL scrollableWhenExcepted; @property(nonatomic, strong) STAccessoryView *dataZeroView; @property(nonatomic, strong) STAccessoryView *dataExceptionView; //// 指示器 @property(nonatomic, strong) STIndicatorView *indicatorView; /// default return YES - (BOOL)shouldDisplayDataZeroView:(UIView *)zeroView; - (BOOL)shouldDisplayDataExceptionView:(UIView *)exceptionView error:(NSError *)error; - (void)displayDataZeroView:(UIView *)zeroView; - (void)displayDataExceptionView:(UIView *)exceptionView error:(NSError *)error; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTextView.h ================================================ // // STTextView.h // STKit // // Created by SunJiangting on 14-1-7. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import #import /// 提供了有placeHolder的文本输入框 @interface STTextView : UITextView @property(STPROPERTYNONNULL nonatomic, strong, readonly) STLabel *placeholderLabel; @property(STPROPERTYNULLABLE nonatomic, copy) NSString *placeholder; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTheme.h ================================================ // // STTheme.h // STKit // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @interface STTheme : NSObject /** * @abstract 为某个类下的某个key赋值。 * * @param value 该主题的值,一般为 UIFont/UIColor等类型 */ - (void)setThemeValue:(id)value forKey:(NSString *)key whenContainedIn:(Class)containerClass; - (id)themeValueForKey:(NSString *)key whenContainedIn:(Class)containerClass; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STThemeManager.h ================================================ // // STThemeManager.h // STKit // // Created by SunJiangting on 13-12-19. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @class STTheme; @interface STThemeManager : NSObject + (instancetype)sharedThemeManager; + (STTheme *)currentTheme; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STTrashManager.h ================================================ // // STTrashManager.h // STKit // // Created by SunJiangting on 15/10/12. // Copyright © 2015年 SunJiangting. All rights reserved. // #import #import @interface STTrashManager : NSObject + (instancetype)sharedManager; @property(nonatomic) BOOL tryEmptyTrashWhenEnterBackground; /// 移到废纸篓 - (BOOL)trashItemAtPath:(NSString *)path resultingItemPath:(NSString **)outResultingPath error:(NSError **)error; /// 清空废纸篓 - (void)emptyTrashWithCompletionHandler:(void (^)(BOOL finished))completion; /// caclulate all trash size synchronized, will block current thread - (unsigned long long)trashSize; - (void)calculateTrashSizeWithCompletionHandler:(void(^)(unsigned long long size))completionHandler; - (BOOL)isEmptying; - (void)cancel; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STURLCache.h ================================================ // // STURLCache.h // STKit // // Created by SunJiangting on 15-4-20. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import @interface STURLCache : NSURLCache @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STViewController.h ================================================ // // STViewController.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import @interface STViewController : UIViewController @property(nonatomic, assign, getter=isInteractivePopGestureEnabled) BOOL interactivePopGestureEnabled; - (void)backViewControllerAnimated:(BOOL)animated; @end #import #import ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STWaveAnalysis.h ================================================ // // SWaveAnalysis.h // SMood // // Created by SunJiangting on 13-3-21. // Copyright (c) 2013年 sun. All rights reserved. // #import "fft.h" #import #import #define FFT_RESULT_SIZE (1 << (FFT_BUFFER_SIZE_LOG - 1)) #define FFT_AUDIO_BUFFER_SIZE (1 << (FFT_BUFFER_SIZE_LOG + 1)) // 目前采样点为512 typedef struct STAnalysisBuffer { SInt8 channels; // 分析为单声道还是多声道 SInt16 result[2][FFT_RESULT_SIZE]; // 分析后的数据,如果是单声道,则只分析result[0][*] } STAnalysisBuffer; typedef STAnalysisBuffer *STAnalysisBufferRef; /** * @brief 该类主要是对音频数据进行采样分析,主要用到快速傅立叶变换(fft),根据变换之后的值即可对数据进行分量,得到各个频段下的能量 */ @interface STWaveAnalysis : NSObject /// 所有的高度是根据 constraintsHeight 相对计算得来的,默认为100 @property(nonatomic, assign) CGFloat constraintsHeight; // 默认单声道 - (STAnalysisBufferRef)analysisWithData:(NSData *)data; /** * @brief 对data中的数据进行傅立叶变换,采样点为512 * * @param data 需要分析的原始音频数据 * @param channels 音频为单声道还是双声道 * * @return 返回分析后的结果,分析后的结果为二维数组,如果单声道音频,则只有result[0][i] 有值 * @note 所传入的data必须为原始音频数据,如果传入其它音频数据,则不能保证分析的数据是准确的。必须保证data中有512 个short */ - (STAnalysisBufferRef)analysisWithData:(NSData *)data channels:(NSInteger)channels; @end // 获取绘制柱状图所需要的数据 @interface STWaveAnalysis (SWaveBar) // 默认单声道,分量频率为默认值 - (NSArray *)heightForBarWithData:(NSData *)data; // 默认分量频率 - (NSArray *)heightForBarWithData:(NSData *)data channels:(NSInteger)channels; /** * @brief 该方法主要是针对条形图和分量频率对各个频率的能量进行求值 * * @param data 原始音频数据 * @param channels 声道个数 * @param frequency 分量频率 * @return 返回各个分量下的能量值,比如 20k 下的power为40 * @note data必须为原始数据,否则不保证分析结果的准确性。必须保证data的长度包含512个short */ - (NSArray *)heightForBarWithData:(NSData *)data channels:(NSInteger)channels constraintsFrequency:(NSArray *)frequency; @end @interface STWaveAnalysis (SLemuria) - (NSArray *)heightWithData:(NSData *)data channels:(NSInteger)channels constraintsFrequency:(NSArray *)frequency; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STWebViewController.h ================================================ // // STWebViewController.h // STKit // // Created by SunJiangting on 13-11-21. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import /** * @abstract 此ViewController为加载WebView的Controller。一般用于 关于等页面,内提供基本的前进,后退,刷新等网页功能 */ @interface STWebViewController : STViewController /// UIWebView。 @property(nonatomic, readonly, strong) UIWebView *webView; /// 底部导航栏是否hidden,包含网页的前进,后退,刷新等按钮。 @property(nonatomic, assign) BOOL webViewBarHidden; - (void)setWebViewBarHidden:(BOOL)webViewBarHidden animated:(BOOL)animated; /// 加载是是否需要菊花 @property(nonatomic, assign) BOOL showIndicatorWhenLoading; /// designed initializer - (instancetype)initWithURL:(NSURL *)URL; - (instancetype)initWithURLString:(NSString *)URLString; @end @interface STWebViewController (STLocalFile) - (instancetype)initWithContentsOfFile:(NSString *)path; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/STZipArchive.h ================================================ // // STZipArchive.h // STKit // // Created by SunJiangting on 14-5-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface STZipArchive : NSObject { } @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/UIAlertView+STBlock.h ================================================ // // UIAlertView+STBlock.h // STKit // // Created by SunJiangting on 14-10-31. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import typedef void (^STAlertViewDismissBlock)(UIAlertView *alertView, NSUInteger dismissIndex); @interface UIAlertView (STBlock) - (void)st_showWithDismissBlock:(STAlertViewDismissBlock)block; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/UIImageView+STImageLoader.h ================================================ // // UIImageView+STImageLoader.h // STKit // // Created by SunJiangting on 13-11-26. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import "STImageLoader.h" typedef NS_ENUM(NSInteger, STImageState) { STImageStateInitialized, STImageStateDownloading, STImageStateDownloadFinished, STImageStateDownloadFailed, }; /// 图片加载 @interface UIImageView (STImageLoader) @property(nonatomic, readonly, getter=st_isFinished) BOOL st_finished; @property(nonatomic, strong, setter=st_setPlaceholderImage:, getter=st_placeholderImage) UIImage *st_placeholderImage; @property(nonatomic, assign, readonly) STImageState st_state; - (void)st_setImageWithURLString:(NSString *)URLString; - (void)st_setImageWithURLString:(NSString *)URLString finishedHandler:(STImageLoaderHandler)finishedHandler; - (void)st_setImageWithURLString:(NSString *)URLString progressHandler:(STImageProgressHandler)progressHandler finishedHandler:(STImageLoaderHandler)finishedHandler; - (void)st_cancelLoadImageWithURLString:(NSString *)URLString; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/UIKit+STKit.h ================================================ // // UIKit+STKit.h // STKit // // Created by SunJiangting on 13-10-5. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import #import #import ST_EXTERN CGFloat STOnePixel(); ST_EXTERN CGFloat STGetScreenWidth(); ST_EXTERN CGFloat STGetScreenHeight(); ST_EXTERN UIView * ST_NULLABLE STGetStatusBarWindow(); ST_EXTERN CGAffineTransform STTransformMakeRotation(CGPoint center, CGPoint anchorPoint, CGFloat angle); ST_EXTERN CGFloat STGetSystemVersion(); ST_EXTERN NSString * ST_NONNULL STGetSystemVersionString(); ST_EXTERN CGPoint STConvertPointBetweenSize(CGPoint point, CGSize fromSize, CGSize toSize); ST_EXTERN CGRect STConvertFrameBetweenSize(CGRect frame, CGSize fromSize, CGSize toSize); #pragma mark - UIColor Extension ST_ASSUME_NONNULL_BEGIN /// 给UIColor增加rgb的构造方法 @interface UIColor (STExtension) /// 使用rgbValue构造UIColor [UIColor st_colorWithRGB:0xCB553B]; + (UIColor *)st_colorWithRGB:(NSInteger)rgb; /// 使用rgbValue构造UIColor [UIColor st_colorWithRGB:0xCB553B alpha:0.3]; + (UIColor *)st_colorWithRGB:(NSInteger)rgb alpha:(CGFloat)alpha; /// 使用rgb 16进制String构造UIColor [UIColor st_colorWithHexString:@"0xFFFFFF"]; + (STNULLABLE UIColor *)st_colorWithHexString:(STNULLABLE NSString *)hexString; + (STNULLABLE UIColor *)st_colorWithHexString:(STNULLABLE NSString *)hexString alpha:(CGFloat)alpha; @end ST_ASSUME_NONNULL_END #pragma mark - UIView Extension @interface UIView (STKit) #pragma mark - UIView Frame Accesser /** * @abstract getter CGRectGetMinY(self.frame) setter frame.origin.y = top; */ @property(nonatomic) CGFloat top; /** * @abstract getter CGRectGetMaxY(self.frame) setter frame.origin.y = bottom - height; */ @property(nonatomic) CGFloat bottom; /** * @abstract getter CGRectGetMinX(self.frame) setter frame.origin.x = left; */ @property(nonatomic) CGFloat left; /** * @abstract getter CGRectGetMaxX(self.frame) setter frame.origin.x = right - width; */ @property(nonatomic) CGFloat right; /** * @abstract getter CGRectGetWidth(self.frame) setter frame.size.width = width; */ @property(nonatomic) CGFloat width; /** * @abstract getter CGRectGetHeight(self.frame) setter frame.size.height = height; */ @property(nonatomic) CGFloat height; /** * @abstract getter frame.origin setter frame.origin = origin; */ @property(nonatomic) CGPoint origin; /** * @abstract getter frame.size setter frame.size = size; */ @property(nonatomic) CGSize size; /** * @abstract getter self.center.x setter center.x = centerX; */ @property(nonatomic) CGFloat centerX; /** * @abstract getter self.center.y setter center.y = centerY; */ @property(nonatomic) CGFloat centerY; /** * @abstract getter CGRectGetWidth(frame) / 2 */ @property(nonatomic, readonly) CGFloat inCenterX; /** * @abstract getter CGRectGetHeight(frame) / 2 */ @property(nonatomic, readonly) CGFloat inCenterY; /** * @abstract getter (inCenterX, inCenterY) */ @property(nonatomic, readonly) CGPoint inCenter; /** * @abstract location in screen */ @property(nonatomic, readonly) CGFloat screenX; /** * @abstract location in screen */ @property(nonatomic, readonly) CGFloat screenY; /** * @abstract removeAllSubviews */ - (void)removeAllSubviews; /** * @abstract view's viewController if the view has one */ - (STNULLABLE UIViewController *)viewController; /** * @abstract view的superview中,是否包含某一类的view * * @param viewClass superview 的 class * @return view是否被添加到 类型为viewClass的superview上面 */ - (BOOL)st_isDescendantOfClass:(STNONNULL Class)viewClass; /** * @abstract 递归查找view的superview,直到找到类型为viewClass的view * * @param viewClass superview 的 class * @return 第一个满足类型为viewClass的superview */ - (STNULLABLE UIView *)st_superviewWithClass:(STNONNULL Class)viewClass; /** * @abstract 递归遍历该view,找到该view中的所有subview类型为class的view * * @param viewClass subview 的 class * @return 所有类型为class的subview */ - (STNULLABLE NSArray *)st_viewWithClass:(STNONNULL Class)viewClass; /** * @abstract 为该View添加轻拍手势 * * @param target 接受手势通知的对象 * @param action 回调方法 */ - (void)st_addTouchTarget:(STNULLABLE id)target action:(STNULLABLE SEL)action; - (void)st_removeTouchTarget:(STNULLABLE id)target action:(STNULLABLE SEL)action; /** * Return the x coordinate on the screen, taking into account scroll views. */ @property(nonatomic, readonly) CGFloat screenViewX; /** * Return the y coordinate on the screen, taking into account scroll views. */ @property(nonatomic, readonly) CGFloat screenViewY; /** * Return the view frame on the screen, taking into account scroll views. */ @property(nonatomic, readonly) CGRect screenFrame; /** * Return the width in portrait or the height in landscape. */ @property(nonatomic, readonly) CGFloat orientationWidth; /** * Return the height in portrait or the width in landscape. */ @property(nonatomic, readonly) CGFloat orientationHeight; /** * Calculates the offset of this view from another view in screen coordinates. * * otherView should be a parent view of this view. */ - (CGPoint)st_offsetFromView:(STNONNULL UIView *)otherView; @property(nonatomic) CGPoint anchorPoint; @end @interface UIScrollView (STKit) @property(nonatomic) CGFloat contentOffsetX; @property(nonatomic) CGFloat contentOffsetY; @property(nonatomic) CGFloat contentWidth; @property(nonatomic) CGFloat contentHeight; @end ST_ASSUME_NONNULL_BEGIN typedef BOOL (^STPanGestureShouldBeginHandler)(UIScrollView *, UIPanGestureRecognizer *); @interface UIScrollView (STGestureShouldBegin) // //(CollectionView, UIPanGestureRecognizer) -> Bool @property(STPROPERTYNULLABLE nonatomic, strong, setter=st_setPanGestureShouldHandler:, getter=st_panGestureShouldHandler) STPanGestureShouldBeginHandler st_panGestureShouldHandler; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN @interface UIResponder (STResponder) /** * @abstract 递归查找view的nextResponder,直到找到类型为class的Responder * * @param class nextResponder 的 class * @return 第一个满足类型为class的UIResponder */ - (STNULLABLE UIResponder *)st_nextResponderWithClass:(Class)aClass; /// 查找firstResponder - (STNULLABLE UIResponder *)st_findFirstResponder; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN /** * @abstract hitTestBlock * * @param 其余参数 参考UIView hitTest:withEvent: * @param returnSuper 是否返回Super的值。如果*returnSuper=YES,则代表会返回 super hitTest:withEvent:, 否则则按照block的返回值(即使是nil) * * @discussion 切记,千万不要在这个block中调用self hitTest:withPoint,否则则会造成递归调用。这个方法就是hitTest:withEvent的一个代替。 */ typedef UIView * ST_NULLABLE (^STHitTestViewBlock)(CGPoint point, UIEvent *event, BOOL *returnSuper); typedef BOOL (^STPointInsideBlock)(CGPoint point, UIEvent *event, BOOL *returnSuper); @interface UIView (STHitTest) /// althought this is strong ,but i deal it with copy @property(STPROPERTYNULLABLE nonatomic, strong) STHitTestViewBlock hitTestBlock; @property(STPROPERTYNULLABLE nonatomic, strong) STPointInsideBlock pointInsideBlock; @end ST_ASSUME_NONNULL_END /// 是否弹起系统Menu菜单(选择/复制/拷贝等等) @interface UITextField (STMenuController) /// default YES. @property(nonatomic, assign, getter=isMenuEnabled) BOOL menuEnabled; @end /// 是否弹起系统Menu菜单(选择/复制/拷贝等等) @interface UITextView (STMenuController) /// default YES. @property(nonatomic, assign, getter=isMenuEnabled) BOOL menuEnabled; @end /** * @abstract 图片类型。 * * @param STImageDataTypeUnknown 未知类型 */ typedef NS_ENUM(NSInteger, STImageDataType) { STImageDataTypeUnknown, STImageDataTypePCX, // 文件头 共1字节 0A STImageDataTypeBMP, // 文件头 共2字节 42 4d STImageDataTypeJPEG, // 文件头 共2字节 ff d8 文件尾 ff d9 STImageDataTypePNG, // 文件头 共8字节 89 50 4e 47 0d 0a 1a 0a STImageDataTypeGIF, // 文件头 共6字节 47 49 46 38 39/37 61 STImageDataTypeWebP, // 文件头 共6字节 47 49 46 38 39/37 61 }; /** * @abstract 根据Data内容,解析文件头。 */ @interface NSData (STImage) /// 根据data前8字节解析图片类型。@see STImageDataType - (STImageDataType)imageType; @end /** * @abstract 根据Data内容,解析图片。 */ @interface UIImage (STImage) /// 判断图片类型,支持GIF解析 + (STNULLABLE UIImage *)st_imageWithSTData:(STNULLABLE NSData *)data; @end /// imageNamed:.png/@2x.png/-568h@2x.png. /// gif image must has suffix .gif, named:xxx.gif or xxx@2x.gif @interface UIImage (STImageNamed) @end /** * @abstract! * * STBlurEffectStyleLight 比较淡色的毛玻璃效果,系统原生的NavigationBar毛玻璃效果 * STBlurEffectStyleExtraLight 系统从最底部往上滑动的设置毛玻璃效果 * STBlurEffectStyleDark 通知中心的毛玻璃效果 */ typedef NS_ENUM(NSInteger, STBlurEffectStyle) { STBlurEffectStyleNone, STBlurEffectStyleExtraLight, STBlurEffectStyleLight, STBlurEffectStyleDark }; ST_ASSUME_NONNULL_BEGIN /// 给图片添加毛玻璃效果 @interface UIImage (STBlurImage) - (UIImage *)st_blurImageWithStyle:(STBlurEffectStyle)style; - (UIImage *)st_blurImageWithTintColor:(STNULLABLE UIColor *)tintColor; - (UIImage *)st_blurImageWithRadius:(CGFloat)blurRadius tintColor:(STNULLABLE UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor; - (UIImage *)st_blurImageWithRadius:(CGFloat)blurRadius tintColor:(STNULLABLE UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(STNULLABLE UIImage *)maskImage; - (UIImage *)st_imageWithRenderingTintColor:(STNULLABLE UIColor *)tintColor; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN /// UIView 截图 @interface UIView (STSnapshot) /// 截图后的image - (UIImage *)st_snapshotImage; /// 截取View中的某一小块 - (UIImage *)st_snapshotImageInRect:(CGRect)rect; /// 把 UIView的transform也放进截图中 - (UIImage *)st_transformedSnapshotImage; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN @interface UIView (STBlur) - (UIImage *)st_blurImage; - (STNULLABLE UIView *)st_statusBarWindow; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN typedef void (^STInvokeHandler)(void); @interface UICollectionView (STReloadData) @property(STPROPERTYNULLABLE nonatomic, strong) STInvokeHandler willReloadData; @property(STPROPERTYNULLABLE nonatomic, strong) STInvokeHandler didReloadData; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN @interface UITableView (STReloadData) @property(STPROPERTYNULLABLE nonatomic, strong) STInvokeHandler willReloadData; @property(STPROPERTYNULLABLE nonatomic, strong) STInvokeHandler didReloadData; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN @interface UIActionSheet (STKit) - (instancetype)initWithTitle:(STNULLABLE NSString *)title delegate:(STNULLABLE id)delegate cancelButtonTitle:(STNULLABLE NSString *)cancelButtonTitle destructiveButtonTitle:(STNULLABLE NSString *)destructiveButtonTitle otherButtonTitleArray:(STNULLABLE NSArray *)otherButtonTitleArray; @end ST_ASSUME_NONNULL_END ST_ASSUME_NONNULL_BEGIN @interface UIImage (STSubimage) - (UIImage *)st_fixedOrientationImage; - (UIImage *)st_imageRotatedByRadians:(CGFloat)radians; - (UIImage *)st_imageRotatedByDegrees:(CGFloat)degrees; + (UIImage *)st_imageWithColor:(UIColor *)color; + (UIImage *)st_imageWithColor:(UIColor *)color size:(CGSize)size; /// 某个rect下的子图像 - (UIImage *)st_subimageInRect:(CGRect)rect; - (UIImage *)st_imageWithTransform:(CGAffineTransform)transform; - (UIImage *)st_imageConstrainedToSize:(CGSize)size; - (UIImage *)st_imageConstrainedToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode; @end ST_ASSUME_NONNULL_END ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/UIView+STConstraint.h ================================================ // // UIView+STConstraint.h // STKit // // Created by SunJiangting on 15-1-21. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import @interface UIView (STConstraint) - (STNULLABLE NSArray *)st_constraintsWithFirstItem:(STNULLABLE UIView *)firstItem; - (STNULLABLE NSArray *)st_constraintsWithFirstItem:(STNULLABLE UIView *)firstItem firstAttribute:(NSLayoutAttribute)attribute; @end ================================================ FILE: STKitDemo/Classes/STKit.framework/Headers/fft.h ================================================ /***************************************************************************** * fft.h: Headers for iterative implementation of a FFT ***************************************************************************** * $Id: 942fd5d1af270167dc97fc10482cfedb3f1f4af4 $ * * Mainly taken from XMMS's code * * Authors: Richard Boulton * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifndef _FFT_H_ #define _FFT_H_ #define FFT_BUFFER_SIZE_LOG 9 #define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG) /* sound sample - should be an signed 16 bit value */ typedef short int sound_sample; struct _struct_fft_state { /* Temporary data stores to perform FFT in. */ float real[FFT_BUFFER_SIZE]; float imag[FFT_BUFFER_SIZE]; /* */ unsigned int bitReverse[FFT_BUFFER_SIZE]; /* The next two tables could be made to use less space in memory, since they * overlap hugely, but hey. */ float sintable[FFT_BUFFER_SIZE / 2]; float costable[FFT_BUFFER_SIZE / 2]; }; /* FFT prototypes */ typedef struct _struct_fft_state fft_state; fft_state *visual_fft_init (void); void fft_perform (const sound_sample *input, float *output, fft_state *state); void fft_close (fft_state *state); #endif /* _FFT_H_ */ ================================================ FILE: STKitDemo/Classes/STKit.framework/STKit ================================================ [File too large to display: 41.1 MB] ================================================ FILE: STKitDemo/LaunchScreen.xib ================================================ ================================================ FILE: STKitDemo/Main.storyboard ================================================ ================================================ FILE: STKitDemo/Resources/licenses.html ================================================ STKitDemo开源组件

STKitDemo使用的开源组件

STKitDemo在开发过程中使用了下列第三方开源组件,感谢开源社区对我们的帮助和对整个互联网的贡献。

SimplePing


IMPORTANT: This Apple software is supplied to you by Apple Inc.
("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or
redistribution of this Apple software constitutes acceptance of
these terms.  If you do not agree with these terms, please do
not use, install, modify or redistribute this Apple software.

In consideration of your agreement to abide by the following
terms, and subject to these terms, Apple grants you a personal,
non-exclusive license, under Apple's copyrights in this
original Apple software (the "Apple Software"), to use,
reproduce, modify and redistribute the Apple Software, with or
without modifications, in source and/or binary forms; provided
that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the
following text and disclaimers in all such redistributions of
the Apple Software. Neither the name, trademarks, service marks
or logos of Apple Inc. may be used to endorse or promote
products derived from the Apple Software without specific prior
written permission from Apple.  Except as expressly stated in
this notice, no other rights or licenses, express or implied,
are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or
by other works in which the Apple Software may be incorporated.

The Apple Software is provided by Apple on an "AS IS" basis.
APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING
THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
COMBINATION WITH YOUR PRODUCTS.

IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT,
INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY
OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

MZCroppableView


Copyright (c) 2012 Javier Berlana, mo2o.com

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

ZipArchive


Copyright (C) 2010-2012 Matt Connolly, Edward Patel, et al

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Copyright (C) 1998-2009 Gilles Vollant

This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

SCSiriWaveformView


    The MIT License (MIT)
    
    Copyright (c) [2013] [Stefan Ceriu]
    
    Permission is hereby granted, free of charge, to any person obtaining a copy of
    this software and associated documentation files (the "Software"), to deal in
    the Software without restriction, including without limitation the rights to
    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
    the Software, and to permit persons to whom the Software is furnished to do so,
    subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

fft


    $Id: 2151e9be79b9600f0c983117ad7bd64eb5ef6e83 $
    
    Mainly taken from XMMS's code
    
    Authors: Richard Boulton <richard@tartarus.org>
             Ralph Loader <suckfish@ihug.co.nz>
    
    This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or(at your option) any later version.
    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
            
    GNU GENERAL PUBLIC LICENSE
    Version 3, 29 June 2007
    
    Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
    Everyone is permitted to copy and distribute verbatim copies
    of this license document, but changing it is not allowed.
    
    Preamble
    
    The GNU General Public License is a free, copyleft license for
    software and other kinds of works.
    
    The licenses for most software and other practical works are designed
    to take away your freedom to share and change the works.  By contrast,
    the GNU General Public License is intended to guarantee your freedom to
    share and change all versions of a program--to make sure it remains free
    software for all its users.  We, the Free Software Foundation, use the
    GNU General Public License for most of our software; it applies also to
    any other work released this way by its authors.  You can apply it to
    your programs, too.
    
    When we speak of free software, we are referring to freedom, not
    price.  Our General Public Licenses are designed to make sure that you
    have the freedom to distribute copies of free software (and charge for
    them if you wish), that you receive source code or can get it if you
    want it, that you can change the software or use pieces of it in new
    free programs, and that you know you can do these things.
    
    To protect your rights, we need to prevent others from denying you
    these rights or asking you to surrender the rights.  Therefore, you have
    certain responsibilities if you distribute copies of the software, or if
    you modify it: responsibilities to respect the freedom of others.
    
    For example, if you distribute copies of such a program, whether
    gratis or for a fee, you must pass on to the recipients the same
    freedoms that you received.  You must make sure that they, too, receive
    or can get the source code.  And you must show them these terms so they
    know their rights.
    
    Developers that use the GNU GPL protect your rights with two steps:
    (1) assert copyright on the software, and (2) offer you this License
    giving you legal permission to copy, distribute and/or modify it.
    
    For the developers' and authors' protection, the GPL clearly explains
    that there is no warranty for this free software.  For both users' and
    authors' sake, the GPL requires that modified versions be marked as
    changed, so that their problems will not be attributed erroneously to
    authors of previous versions.
    
    Some devices are designed to deny users access to install or run
    modified versions of the software inside them, although the manufacturer
    can do so.  This is fundamentally incompatible with the aim of
    protecting users' freedom to change the software.  The systematic
    pattern of such abuse occurs in the area of products for individuals to
    use, which is precisely where it is most unacceptable.  Therefore, we
    have designed this version of the GPL to prohibit the practice for those
    products.  If such problems arise substantially in other domains, we
    stand ready to extend this provision to those domains in future versions
    of the GPL, as needed to protect the freedom of users.
    
    Finally, every program is threatened constantly by software patents.
    States should not allow patents to restrict development and use of
    software on general-purpose computers, but in those that do, we wish to
    avoid the special danger that patents applied to a free program could
    make it effectively proprietary.  To prevent this, the GPL assures that
    patents cannot be used to render the program non-free.
    
    The precise terms and conditions for copying, distribution and
    modification follow.
    
    TERMS AND CONDITIONS
    
    0. Definitions.
    
    "This License" refers to version 3 of the GNU General Public License.
    
    "Copyright" also means copyright-like laws that apply to other kinds of
    works, such as semiconductor masks.
    
    "The Program" refers to any copyrightable work licensed under this
    License.  Each licensee is addressed as "you".  "Licensees" and
    "recipients" may be individuals or organizations.
    
    To "modify" a work means to copy from or adapt all or part of the work
    in a fashion requiring copyright permission, other than the making of an
    exact copy.  The resulting work is called a "modified version" of the
    earlier work or a work "based on" the earlier work.
    
    A "covered work" means either the unmodified Program or a work based
    on the Program.
    
    To "propagate" a work means to do anything with it that, without
    permission, would make you directly or secondarily liable for
    infringement under applicable copyright law, except executing it on a
    computer or modifying a private copy.  Propagation includes copying,
    distribution (with or without modification), making available to the
    public, and in some countries other activities as well.
    
    To "convey" a work means any kind of propagation that enables other
    parties to make or receive copies.  Mere interaction with a user through
    a computer network, with no transfer of a copy, is not conveying.
    
    An interactive user interface displays "Appropriate Legal Notices"
    to the extent that it includes a convenient and prominently visible
    feature that (1) displays an appropriate copyright notice, and (2)
    tells the user that there is no warranty for the work (except to the
    extent that warranties are provided), that licensees may convey the
    work under this License, and how to view a copy of this License.  If
    the interface presents a list of user commands or options, such as a
    menu, a prominent item in the list meets this criterion.
    
    1. Source Code.
    
    The "source code" for a work means the preferred form of the work
    for making modifications to it.  "Object code" means any non-source
    form of a work.
    
    A "Standard Interface" means an interface that either is an official
    standard defined by a recognized standards body, or, in the case of
    interfaces specified for a particular programming language, one that
    is widely used among developers working in that language.
    
    The "System Libraries" of an executable work include anything, other
    than the work as a whole, that (a) is included in the normal form of
    packaging a Major Component, but which is not part of that Major
    Component, and (b) serves only to enable use of the work with that
    Major Component, or to implement a Standard Interface for which an
    implementation is available to the public in source code form.  A
    "Major Component", in this context, means a major essential component
    (kernel, window system, and so on) of the specific operating system
    (if any) on which the executable work runs, or a compiler used to
    produce the work, or an object code interpreter used to run it.
    
    The "Corresponding Source" for a work in object code form means all
    the source code needed to generate, install, and (for an executable
    work) run the object code and to modify the work, including scripts to
    control those activities.  However, it does not include the work's
    System Libraries, or general-purpose tools or generally available free
    programs which are used unmodified in performing those activities but
    which are not part of the work.  For example, Corresponding Source
    includes interface definition files associated with source files for
    the work, and the source code for shared libraries and dynamically
    linked subprograms that the work is specifically designed to require,
    such as by intimate data communication or control flow between those
    subprograms and other parts of the work.
    
    The Corresponding Source need not include anything that users
    can regenerate automatically from other parts of the Corresponding
    Source.
    
    The Corresponding Source for a work in source code form is that
    same work.
    
    2. Basic Permissions.
    
    All rights granted under this License are granted for the term of
    copyright on the Program, and are irrevocable provided the stated
    conditions are met.  This License explicitly affirms your unlimited
    permission to run the unmodified Program.  The output from running a
    covered work is covered by this License only if the output, given its
    content, constitutes a covered work.  This License acknowledges your
    rights of fair use or other equivalent, as provided by copyright law.
    
    You may make, run and propagate covered works that you do not
    convey, without conditions so long as your license otherwise remains
    in force.  You may convey covered works to others for the sole purpose
    of having them make modifications exclusively for you, or provide you
    with facilities for running those works, provided that you comply with
    the terms of this License in conveying all material for which you do
    not control copyright.  Those thus making or running the covered works
    for you must do so exclusively on your behalf, under your direction
    and control, on terms that prohibit them from making any copies of
    your copyrighted material outside their relationship with you.
    
    Conveying under any other circumstances is permitted solely under
    the conditions stated below.  Sublicensing is not allowed; section 10
    makes it unnecessary.
    
    3. Protecting Users' Legal Rights From Anti-Circumvention Law.
    
    No covered work shall be deemed part of an effective technological
    measure under any applicable law fulfilling obligations under article
    11 of the WIPO copyright treaty adopted on 20 December 1996, or
    similar laws prohibiting or restricting circumvention of such
    measures.
    
    When you convey a covered work, you waive any legal power to forbid
    circumvention of technological measures to the extent such circumvention
    is effected by exercising rights under this License with respect to
    the covered work, and you disclaim any intention to limit operation or
    modification of the work as a means of enforcing, against the work's
    users, your or third parties' legal rights to forbid circumvention of
    technological measures.
    
    4. Conveying Verbatim Copies.
    
    You may convey verbatim copies of the Program's source code as you
    receive it, in any medium, provided that you conspicuously and
    appropriately publish on each copy an appropriate copyright notice;
    keep intact all notices stating that this License and any
    non-permissive terms added in accord with section 7 apply to the code;
    keep intact all notices of the absence of any warranty; and give all
    recipients a copy of this License along with the Program.
    
    You may charge any price or no price for each copy that you convey,
    and you may offer support or warranty protection for a fee.
    
    5. Conveying Modified Source Versions.
    
    You may convey a work based on the Program, or the modifications to
    produce it from the Program, in the form of source code under the
    terms of section 4, provided that you also meet all of these conditions:
    
    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.
    
    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".
    
    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.
    
    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.
    
    A compilation of a covered work with other separate and independent
    works, which are not by their nature extensions of the covered work,
    and which are not combined with it such as to form a larger program,
    in or on a volume of a storage or distribution medium, is called an
    "aggregate" if the compilation and its resulting copyright are not
    used to limit the access or legal rights of the compilation's users
    beyond what the individual works permit.  Inclusion of a covered work
    in an aggregate does not cause this License to apply to the other
    parts of the aggregate.
    
    6. Conveying Non-Source Forms.
    
    You may convey a covered work in object code form under the terms
    of sections 4 and 5, provided that you also convey the
    machine-readable Corresponding Source under the terms of this License,
    in one of these ways:
    
    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.
    
    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.
    
    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.
    
    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.
    
    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.
    
    A separable portion of the object code, whose source code is excluded
    from the Corresponding Source as a System Library, need not be
    included in conveying the object code work.
    
    A "User Product" is either (1) a "consumer product", which means any
    tangible personal property which is normally used for personal, family,
    or household purposes, or (2) anything designed or sold for incorporation
    into a dwelling.  In determining whether a product is a consumer product,
    doubtful cases shall be resolved in favor of coverage.  For a particular
    product received by a particular user, "normally used" refers to a
    typical or common use of that class of product, regardless of the status
    of the particular user or of the way in which the particular user
    actually uses, or expects or is expected to use, the product.  A product
    is a consumer product regardless of whether the product has substantial
    commercial, industrial or non-consumer uses, unless such uses represent
    the only significant mode of use of the product.
    
    "Installation Information" for a User Product means any methods,
    procedures, authorization keys, or other information required to install
    and execute modified versions of a covered work in that User Product from
    a modified version of its Corresponding Source.  The information must
    suffice to ensure that the continued functioning of the modified object
    code is in no case prevented or interfered with solely because
    modification has been made.
    
    If you convey an object code work under this section in, or with, or
    specifically for use in, a User Product, and the conveying occurs as
    part of a transaction in which the right of possession and use of the
    User Product is transferred to the recipient in perpetuity or for a
    fixed term (regardless of how the transaction is characterized), the
    Corresponding Source conveyed under this section must be accompanied
    by the Installation Information.  But this requirement does not apply
    if neither you nor any third party retains the ability to install
    modified object code on the User Product (for example, the work has
    been installed in ROM).
    
    The requirement to provide Installation Information does not include a
    requirement to continue to provide support service, warranty, or updates
    for a work that has been modified or installed by the recipient, or for
    the User Product in which it has been modified or installed.  Access to a
    network may be denied when the modification itself materially and
    adversely affects the operation of the network or violates the rules and
    protocols for communication across the network.
    
    Corresponding Source conveyed, and Installation Information provided,
    in accord with this section must be in a format that is publicly
    documented (and with an implementation available to the public in
    source code form), and must require no special password or key for
    unpacking, reading or copying.
    
    7. Additional Terms.
    
    "Additional permissions" are terms that supplement the terms of this
    License by making exceptions from one or more of its conditions.
    Additional permissions that are applicable to the entire Program shall
    be treated as though they were included in this License, to the extent
    that they are valid under applicable law.  If additional permissions
    apply only to part of the Program, that part may be used separately
    under those permissions, but the entire Program remains governed by
    this License without regard to the additional permissions.
    
    When you convey a copy of a covered work, you may at your option
    remove any additional permissions from that copy, or from any part of
    it.  (Additional permissions may be written to require their own
    removal in certain cases when you modify the work.)  You may place
    additional permissions on material, added by you to a covered work,
    for which you have or can give appropriate copyright permission.
    
    Notwithstanding any other provision of this License, for material you
    add to a covered work, you may (if authorized by the copyright holders of
    that material) supplement the terms of this License with terms:
    
    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or
    
    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or
    
    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or
    
    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or
    
    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or
    
    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.
    
    All other non-permissive additional terms are considered "further
    restrictions" within the meaning of section 10.  If the Program as you
    received it, or any part of it, contains a notice stating that it is
    governed by this License along with a term that is a further
    restriction, you may remove that term.  If a license document contains
    a further restriction but permits relicensing or conveying under this
    License, you may add to a covered work material governed by the terms
    of that license document, provided that the further restriction does
    not survive such relicensing or conveying.
    
    If you add terms to a covered work in accord with this section, you
    must place, in the relevant source files, a statement of the
    additional terms that apply to those files, or a notice indicating
    where to find the applicable terms.
    
    Additional terms, permissive or non-permissive, may be stated in the
    form of a separately written license, or stated as exceptions;
    the above requirements apply either way.
    
    8. Termination.
    
    You may not propagate or modify a covered work except as expressly
    provided under this License.  Any attempt otherwise to propagate or
    modify it is void, and will automatically terminate your rights under
    this License (including any patent licenses granted under the third
    paragraph of section 11).
    
    However, if you cease all violation of this License, then your
    license from a particular copyright holder is reinstated (a)
    provisionally, unless and until the copyright holder explicitly and
    finally terminates your license, and (b) permanently, if the copyright
    holder fails to notify you of the violation by some reasonable means
    prior to 60 days after the cessation.
    
    Moreover, your license from a particular copyright holder is
    reinstated permanently if the copyright holder notifies you of the
    violation by some reasonable means, this is the first time you have
    received notice of violation of this License (for any work) from that
    copyright holder, and you cure the violation prior to 30 days after
    your receipt of the notice.
    
    Termination of your rights under this section does not terminate the
    licenses of parties who have received copies or rights from you under
    this License.  If your rights have been terminated and not permanently
    reinstated, you do not qualify to receive new licenses for the same
    material under section 10.
    
    9. Acceptance Not Required for Having Copies.
    
    You are not required to accept this License in order to receive or
    run a copy of the Program.  Ancillary propagation of a covered work
    occurring solely as a consequence of using peer-to-peer transmission
    to receive a copy likewise does not require acceptance.  However,
    nothing other than this License grants you permission to propagate or
    modify any covered work.  These actions infringe copyright if you do
    not accept this License.  Therefore, by modifying or propagating a
    covered work, you indicate your acceptance of this License to do so.
    
    10. Automatic Licensing of Downstream Recipients.
    
    Each time you convey a covered work, the recipient automatically
    receives a license from the original licensors, to run, modify and
    propagate that work, subject to this License.  You are not responsible
    for enforcing compliance by third parties with this License.
    
    An "entity transaction" is a transaction transferring control of an
    organization, or substantially all assets of one, or subdividing an
    organization, or merging organizations.  If propagation of a covered
    work results from an entity transaction, each party to that
    transaction who receives a copy of the work also receives whatever
    licenses to the work the party's predecessor in interest had or could
    give under the previous paragraph, plus a right to possession of the
    Corresponding Source of the work from the predecessor in interest, if
    the predecessor has it or can get it with reasonable efforts.
    
    You may not impose any further restrictions on the exercise of the
    rights granted or affirmed under this License.  For example, you may
    not impose a license fee, royalty, or other charge for exercise of
    rights granted under this License, and you may not initiate litigation
    (including a cross-claim or counterclaim in a lawsuit) alleging that
    any patent claim is infringed by making, using, selling, offering for
    sale, or importing the Program or any portion of it.
    
    11. Patents.
    
    A "contributor" is a copyright holder who authorizes use under this
    License of the Program or a work on which the Program is based.  The
    work thus licensed is called the contributor's "contributor version".
    
    A contributor's "essential patent claims" are all patent claims
    owned or controlled by the contributor, whether already acquired or
    hereafter acquired, that would be infringed by some manner, permitted
    by this License, of making, using, or selling its contributor version,
    but do not include claims that would be infringed only as a
    consequence of further modification of the contributor version.  For
    purposes of this definition, "control" includes the right to grant
    patent sublicenses in a manner consistent with the requirements of
    this License.
    
    Each contributor grants you a non-exclusive, worldwide, royalty-free
    patent license under the contributor's essential patent claims, to
    make, use, sell, offer for sale, import and otherwise run, modify and
    propagate the contents of its contributor version.
    
    In the following three paragraphs, a "patent license" is any express
    agreement or commitment, however denominated, not to enforce a patent
    (such as an express permission to practice a patent or covenant not to
    sue for patent infringement).  To "grant" such a patent license to a
    party means to make such an agreement or commitment not to enforce a
    patent against the party.
    
    If you convey a covered work, knowingly relying on a patent license,
    and the Corresponding Source of the work is not available for anyone
    to copy, free of charge and under the terms of this License, through a
    publicly available network server or other readily accessible means,
    then you must either (1) cause the Corresponding Source to be so
    available, or (2) arrange to deprive yourself of the benefit of the
    patent license for this particular work, or (3) arrange, in a manner
    consistent with the requirements of this License, to extend the patent
    license to downstream recipients.  "Knowingly relying" means you have
    actual knowledge that, but for the patent license, your conveying the
    covered work in a country, or your recipient's use of the covered work
    in a country, would infringe one or more identifiable patents in that
    country that you have reason to believe are valid.
    
    If, pursuant to or in connection with a single transaction or
    arrangement, you convey, or propagate by procuring conveyance of, a
    covered work, and grant a patent license to some of the parties
    receiving the covered work authorizing them to use, propagate, modify
    or convey a specific copy of the covered work, then the patent license
    you grant is automatically extended to all recipients of the covered
    work and works based on it.
    
    A patent license is "discriminatory" if it does not include within
    the scope of its coverage, prohibits the exercise of, or is
    conditioned on the non-exercise of one or more of the rights that are
    specifically granted under this License.  You may not convey a covered
    work if you are a party to an arrangement with a third party that is
    in the business of distributing software, under which you make payment
    to the third party based on the extent of your activity of conveying
    the work, and under which the third party grants, to any of the
    parties who would receive the covered work from you, a discriminatory
    patent license (a) in connection with copies of the covered work
    conveyed by you (or copies made from those copies), or (b) primarily
    for and in connection with specific products or compilations that
    contain the covered work, unless you entered into that arrangement,
    or that patent license was granted, prior to 28 March 2007.
    
    Nothing in this License shall be construed as excluding or limiting
    any implied license or other defenses to infringement that may
    otherwise be available to you under applicable patent law.
    
    12. No Surrender of Others' Freedom.
    
    If conditions are imposed on you (whether by court order, agreement or
    otherwise) that contradict the conditions of this License, they do not
    excuse you from the conditions of this License.  If you cannot convey a
    covered work so as to satisfy simultaneously your obligations under this
    License and any other pertinent obligations, then as a consequence you may
    not convey it at all.  For example, if you agree to terms that obligate you
    to collect a royalty for further conveying from those to whom you convey
    the Program, the only way you could satisfy both those terms and this
    License would be to refrain entirely from conveying the Program.
    
    13. Use with the GNU Affero General Public License.
    
    Notwithstanding any other provision of this License, you have
    permission to link or combine any covered work with a work licensed
    under version 3 of the GNU Affero General Public License into a single
    combined work, and to convey the resulting work.  The terms of this
    License will continue to apply to the part which is the covered work,
    but the special requirements of the GNU Affero General Public License,
    section 13, concerning interaction through a network will apply to the
    combination as such.
    
    14. Revised Versions of this License.
    
    The Free Software Foundation may publish revised and/or new versions of
    the GNU General Public License from time to time.  Such new versions will
    be similar in spirit to the present version, but may differ in detail to
    address new problems or concerns.
    
    Each version is given a distinguishing version number.  If the
    Program specifies that a certain numbered version of the GNU General
    Public License "or any later version" applies to it, you have the
    option of following the terms and conditions either of that numbered
    version or of any later version published by the Free Software
    Foundation.  If the Program does not specify a version number of the
    GNU General Public License, you may choose any version ever published
    by the Free Software Foundation.
    
    If the Program specifies that a proxy can decide which future
    versions of the GNU General Public License can be used, that proxy's
    public statement of acceptance of a version permanently authorizes you
    to choose that version for the Program.
    
    Later license versions may give you additional or different
    permissions.  However, no additional obligations are imposed on any
    author or copyright holder as a result of your choosing to follow a
    later version.
    
    15. Disclaimer of Warranty.
    
    THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
    APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
    HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
    OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
    IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
    ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
    
    16. Limitation of Liability.
    
    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
    WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
    THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
    GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
    USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
    DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
    PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
    EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGES.
    
    17. Interpretation of Sections 15 and 16.
    
    If the disclaimer of warranty and limitation of liability provided
    above cannot be given local legal effect according to their terms,
    reviewing courts shall apply local law that most closely approximates
    an absolute waiver of all civil liability in connection with the
    Program, unless a warranty or assumption of liability accompanies a
    copy of the Program in return for a fee.
    
    END OF TERMS AND CONDITIONS
    
    How to Apply These Terms to Your New Programs
    
    If you develop a new program, and you want it to be of the greatest
    possible use to the public, the best way to achieve this is to make it
    free software which everyone can redistribute and change under these terms.
    
    To do so, attach the following notices to the program.  It is safest
    to attach them to the start of each source file to most effectively
    state the exclusion of warranty; and each file should have at least
    the "copyright" line and a pointer to where the full notice is found.
    
    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
    Also add information on how to contact you by electronic and paper mail.
    
    If the program does terminal interaction, make it output a short
    notice like this when it starts in an interactive mode:
    
    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.
    
    The hypothetical commands `show w' and `show c' should show the appropriate
    parts of the General Public License.  Of course, your program's commands
    might be different; for a GUI interface, you would use an "about box".
    
    You should also get your employer (if you work as a programmer) or school,
    if any, to sign a "copyright disclaimer" for the program, if necessary.
    For more information on this, and how to apply and follow the GNU GPL, see
    <http://www.gnu.org/licenses/>.
    
    The GNU General Public License does not permit incorporating your program
    into proprietary programs.  If your program is a subroutine library, you
    may consider it more useful to permit linking proprietary applications with
    the library.  If this is what you want to do, use the GNU Lesser General
    Public License instead of this License.  But first, please read
    <http://www.gnu.org/philosophy/why-not-lgpl.html>.

ZYQSphereView


GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
================================================ FILE: STKitDemo/STDAppDelegate.h ================================================ // // STDAppDelegate.h // STKitDemo // // Created by SunJiangting on 13-12-6. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import @class SCSiriWaveformView; @interface STDAppDelegate : UIResponder @property(strong, nonatomic) UIWindow *window; - (UIViewController *)startViewController; - (UIViewController *)tabBarController; - (UIViewController *)sideBarController; - (void)replaceRootViewController:(UIViewController *)newViewController animationOptions:(UIViewAnimationOptions)options; @end ================================================ FILE: STKitDemo/STDAppDelegate.m ================================================ // // STDAppDelegate.m // STKitDemo // // Created by SunJiangting on 13-12-6. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDAppDelegate.h" #import "STDSideBarController.h" #import "STDLeftViewController.h" #import "STDTabBarController.h" #import "STDStartViewController.h" #import #import @interface STDAppDelegate () @end @implementation STDAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [self initializeCustomUserSetting]; if ([application respondsToSelector:@selector(setStatusBarStyle:)]) { application.statusBarStyle = UIStatusBarStyleDefault; } application.statusBarHidden = NO; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; if (STGetSystemVersion() < 7) { // iOS6以前statusBar 会有圆角 self.window.windowLevel = UIWindowLevelStatusBar + 1; } self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; NSString *previousStyle = [[STPersistence standardPersistence] valueForKey:@"SelectedStyle"]; if ([previousStyle isEqualToString:@"TabBar"]) { self.window.rootViewController = [self tabBarController]; } else if ([previousStyle isEqualToString:@"SideBar"]) { self.window.rootViewController = [self sideBarController]; } else { self.window.rootViewController = [self startViewController]; } [self.window makeKeyAndVisible]; return YES; } - (UIViewController *)startViewController { [[STPersistence standardPersistence] setValue:@"Start" forKey:@"SelectedStyle"]; return STDStartViewController.new; } - (UIViewController *)tabBarController { [[STPersistence standardPersistence] setValue:@"TabBar" forKey:@"SelectedStyle"]; STDTabBarController *tabBarController = [[STDTabBarController alloc] init]; return tabBarController; } - (UIViewController *)sideBarController { [[STPersistence standardPersistence] setValue:@"SideBar" forKey:@"SelectedStyle"]; STDLeftViewController *leftViewController = [[STDLeftViewController alloc] init]; STDSideBarController *sideBarController = [[STDSideBarController alloc] initWithRootViewController:leftViewController]; sideBarController.st_navigationBarHidden = YES; STNavigationController *navigationController = [[STNavigationController alloc] initWithRootViewController:sideBarController]; return navigationController; } - (void)replaceRootViewController:(UIViewController *)newViewController animationOptions:(UIViewAnimationOptions)options { UIViewController *formerViewController = self.window.rootViewController; if (formerViewController == newViewController) { return; } void (^completion)(BOOL) = ^(BOOL finished) { self.window.rootViewController = newViewController; }; // options 为 0 表示木有动画 if (options == 0) { completion(YES); } else { [UIView transitionFromView:formerViewController.view toView:newViewController.view duration:0.65 options:options completion:completion]; } } - (void)applicationWillResignActive:(UIApplication *)application { // 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. // 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. } - (void)applicationDidEnterBackground:(UIApplication *)application { // 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. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // 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 } - (void)applicationDidBecomeActive:(UIApplication *)application { // 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. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } #pragma mark - PrivateMethod - (void)initializeCustomUserSetting { [[STThemeManager currentTheme] setThemeValue:[UIColor st_colorWithRGB:0x999999] forKey:@"BookTextColor" whenContainedIn:NSClassFromString(@"STRichView")]; UIFont *bookFont = [UIFont fontWithName:@"STHeitiSC-Light" size:21.]; [[STThemeManager currentTheme] setThemeValue:bookFont forKey:@"BookTextFont" whenContainedIn:NSClassFromString(@"STRichView")]; NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:5]; [dict setValue:bookFont forKey:NSFontAttributeName]; [dict setValue:@(2) forKey:NSKernAttributeName]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineSpacing = 4; [dict setValue:paragraphStyle forKey:NSParagraphStyleAttributeName]; [[STThemeManager currentTheme] setThemeValue:dict forKey:@"BookTextAttributes" whenContainedIn:NSClassFromString(@"STRichView")]; } @end ================================================ FILE: STKitDemo/STDemoImages.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-Small.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-Small@2x.png", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-Spotlight-40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-60@2x-1.png", "scale" : "3x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "Icon.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "Icon@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-60@2x.png", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-Small.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-Small@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-Spotlight-40.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-Spotlight-40@2x.png", "scale" : "2x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "Icon-Small-50.png", "scale" : "1x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "Icon-Small-50@2x.png", "scale" : "2x" }, { "size" : "72x72", "idiom" : "ipad", "filename" : "Icon-72.png", "scale" : "1x" }, { "size" : "72x72", "idiom" : "ipad", "filename" : "Icon-72@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76@2x.png", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Base/avatar72.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "avatar72.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "avatar72@2x@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Base/navigation.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "navigation.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "navigation@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/bubble_image_green.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "bubble_image_green.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "bubble_image_green@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/bubble_image_white.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "bubble_image_white.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "bubble_image_white@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/bubble_text_green.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "bubble_text_green.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "bubble_text_green@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/bubble_text_white.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "bubble_text_white.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "bubble_text_white@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/chat_input_send_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "chat_input_send_highlighted.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "chat_input_send_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Chat/chat_input_send_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "chat_input_send_normal.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "chat_input_send_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/FeedCell/feed_cell_background.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "feed_cell_background@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/FeedCell/feed_cell_border.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "feed_cell_border@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/FeedCell/feed_hot_icon.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "feed_hot_icon@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/LaunchImage.launchimage/Contents.json ================================================ { "images" : [ { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "736h", "filename" : "Default-736h@3x.png", "minimum-system-version" : "8.0", "orientation" : "portrait", "scale" : "3x" }, { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "667h", "filename" : "Default-667h@2x.png", "minimum-system-version" : "8.0", "orientation" : "portrait", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "minimum-system-version" : "7.0", "filename" : "Default@2x.png", "scale" : "2x" }, { "extent" : "full-screen", "idiom" : "iphone", "subtype" : "retina4", "filename" : "Default-568h@2x.png", "minimum-system-version" : "7.0", "orientation" : "portrait", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "filename" : "Default.png", "scale" : "1x" }, { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "filename" : "Default@2x.png", "scale" : "2x" }, { "orientation" : "portrait", "idiom" : "iphone", "extent" : "full-screen", "filename" : "Default-568h@2x.png", "subtype" : "retina4", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Navigation/nav_cancel_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "nav_cancel_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Navigation/nav_done_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "nav_done_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Navigation/nav_menu_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "nav_menu_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Navigation/nav_refresh_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "nav_refresh_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Navigation/nav_setting_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "nav_setting_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Porn/article_collect.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "article_collect.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Porn/article_collected.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "article_collected.pdf" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/choose_image_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "choose_image_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/choose_image_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "choose_image_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/hud_done.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "hud_done@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/product_default.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "product_default.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "product_default@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/publish_button_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "publish_button_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/publish_button_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "publish_button_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Publish/publish_tool_bkg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "publish_tool_bkg.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "publish_tool_bkg@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SearchBar/search_cancel_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "search_cancel_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SearchBar/search_cancel_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "search_cancel_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SearchBar/searchbar_bkg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "searchbar_bkg@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SearchBar/textfield_delete_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "textfield_delete_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarAvatar_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarAvatar_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarAvatar_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarAvatar_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarNearby_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarNearby_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarNearby_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarNearby_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarSetting_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarSetting_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarSetting_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarSetting_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarShare_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarShare_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/SideBar/SideBarShare_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "SideBarShare_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_bkg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_bkg@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_message_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_message_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_message_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_message_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_profile_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_profile_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_profile_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_profile_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_receipt_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_receipt_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_receipt_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_receipt_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_service_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_service_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/TabBar/tab_service_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "tab_service_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Test/button_bkg_highlighted.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "button_bkg_highlighted@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Test/button_bkg_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "button_bkg_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Test/home_search_left_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "home_search_left_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Test/home_search_right_normal.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "home_search_right_normal@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/Test/search_history_edit.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "search_history_edit@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole0.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole0@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole1.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole1@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole2.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole2@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole3.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole3@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole4.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole4@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/Menu/wormhole5.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "wormhole5@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/aero_button.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "aero_button@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/viewer_zoom_in.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "viewer_zoom_in.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "viewer_zoom_in@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/UIControls/viewer_zoom_out.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "viewer_zoom_out.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "viewer_zoom_out@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/ViewController/left_account_header.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x", "filename" : "left_account_header.png" }, { "idiom" : "universal", "scale" : "2x", "filename" : "left_account_header@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/ViewController/left_bkg.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "left_bkg@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STDemoImages.xcassets/terms.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "scale" : "2x", "filename" : "terms@2x.png" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: STKitDemo/STKitDemo-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName STKitDemo CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.3.9 CFBundleSignature ???? CFBundleVersion 1.3.9 LSRequiresIPhoneOS NSAppTransportSecurity NSAllowsArbitraryLoads NSLocationAlwaysUsageDescription 技术哥不会随便获取你的地理位置的,就算获取了之后也会加密的,放心吧 NSLocationWhenInUseUsageDescription 技术哥不会随便获取你的地理位置的,就算获取了之后也会加密的,放心吧 NSMainNibFile LaunchScreen UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UIStatusBarHidden UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance ================================================ FILE: STKitDemo/STKitDemo-Prefix.pch ================================================ // // Prefix header // // The contents of this file are implicitly included at the beginning of every source file. // #import #ifndef __IPHONE_5_0 #warning "This project uses features only available in iOS SDK 5.0 and later." #endif #ifdef __OBJC__ #import #import #import "STDCoreDataManager.h" #define kSTKitDemoUmengAppKey @"52c2a67156240b811a09028e" extern void STDLogRemoteWithString(NSString *string, NSString *colorString); #endif ================================================ FILE: STKitDemo/STKitDemo.entitlements ================================================ ================================================ FILE: STKitDemo/STKitDemoInHouse-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName STKitDemo CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.3.9 CFBundleSignature ???? CFBundleVersion 1.3.9 LSRequiresIPhoneOS NSAppTransportSecurity NSAllowsArbitraryLoads NSLocationAlwaysUsageDescription 技术哥不会随便获取你的地理位置的,就算获取了之后也会加密的,放心吧 NSLocationWhenInUseUsageDescription 技术哥不会随便获取你的地理位置的,就算获取了之后也会加密的,放心吧 NSMainNibFile LaunchScreen UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UIStatusBarHidden UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIViewControllerBasedStatusBarAppearance ================================================ FILE: STKitDemo/Settings.bundle/Root.plist ================================================ PreferenceSpecifiers Type PSGroupSpecifier Title 语音识别设置,语音识别功能正在开发,打开该功能之后,就可以用语音来控制页面的跳转。 Type PSToggleSwitchSpecifier Title 语音控制 Key voiceControlEnabled DefaultValue Type PSGroupSpecifier Title 新浪云这几天抽风,xxx.sinaapp.com 不能用,需要替换成xxx.vipsinaapp.com.打开开关相当于纠错 Type PSToggleSwitchSpecifier Title 新浪域名纠正 Key sinaappHostEnabled DefaultValue Type PSGroupSpecifier Title 摇一摇可以激活FLEX插件,FLEX插件是一款开源的辅助产品的插件 Type PSToggleSwitchSpecifier Title 激活FLEX插件 Key FLEXEnabled DefaultValue Type PSGroupSpecifier Title 测试接入Cocos2d游戏 Type PSToggleSwitchSpecifier Title 推箱子游戏 Key BoxManEnabled DefaultValue StringsTable Root ================================================ FILE: STKitDemo/en.lproj/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: STKitDemo/main.m ================================================ // // main.m // STKitDemo // // Created by SunJiangting on 13-12-6. // Copyright (c) 2013年 SunJiangting. All rights reserved. // #import "STDAppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([STDAppDelegate class])); } } ================================================ FILE: STKitDemo.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 0602B499196974150004ACBB /* STDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F6471E891851CD7C00574E94 /* STDAppDelegate.m */; }; 0602B49D196974150004ACBB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F6471E851851CD7C00574E94 /* main.m */; }; 0602B4F6196974150004ACBB /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06C6F9CD1920F0C10028B2B3 /* CoreLocation.framework */; }; 0602B4F7196974150004ACBB /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 06291AE4191F314700EDBD35 /* libxml2.dylib */; }; 0602B4F9196974150004ACBB /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F69CFE261873032B00327D8A /* libz.dylib */; }; 0602B4FA196974150004ACBB /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6E5B875186413A700FF3408 /* AVFoundation.framework */; }; 0602B4FB196974150004ACBB /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6E5B8721864139D00FF3408 /* AudioToolbox.framework */; }; 0602B4FC196974150004ACBB /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F66A09E318522F2A002D0597 /* SystemConfiguration.framework */; }; 0602B4FE196974150004ACBB /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471EE31851CED400574E94 /* QuartzCore.framework */; }; 0602B4FF196974150004ACBB /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471EE11851CECF00574E94 /* MapKit.framework */; }; 0602B500196974150004ACBB /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E7B1851CD7C00574E94 /* CoreGraphics.framework */; }; 0602B501196974150004ACBB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E7D1851CD7C00574E94 /* UIKit.framework */; }; 0602B503196974150004ACBB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E791851CD7C00574E94 /* Foundation.framework */; }; 0602B512196974150004ACBB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F6471E821851CD7C00574E94 /* InfoPlist.strings */; }; 060798F11AC3E68A007C1AA7 /* STDAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 060798F01AC3E68A007C1AA7 /* STDAuthorization.m */; }; 062BAE031B8971C6004380A2 /* STDemoImages.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 06BE56D01A0404CF00FBC4C8 /* STDemoImages.xcassets */; }; 062BAE041B8971C8004380A2 /* STDemoImages.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 06BE56D01A0404CF00FBC4C8 /* STDemoImages.xcassets */; }; 062BAE051B897201004380A2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0634101A19C9EBE3003BC34E /* LaunchScreen.xib */; }; 062BAE061B897202004380A2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0634101A19C9EBE3003BC34E /* LaunchScreen.xib */; }; 0642E2341AE0F3D100B820D1 /* STDLeftViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB636F1A59523F00ABD7D3 /* STDLeftViewController.m */; }; 0642E2361AE0F3D100B820D1 /* STDMoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64761A59523F00ABD7D3 /* STDMoreViewController.m */; }; 0642E2371AE0F3D100B820D1 /* STDSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643C1A59523F00ABD7D3 /* STDSession.m */; }; 0642E2381AE0F3D100B820D1 /* STDTextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637B1A59523F00ABD7D3 /* STDTextTableViewController.m */; }; 0642E2391AE0F3D100B820D1 /* STDLocationPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C518641AAD4E6E00C2B2E3 /* STDLocationPickerController.m */; }; 0642E23A1AE0F3D100B820D1 /* STDLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06479D511ACCF54200A44FB9 /* STDLoadingView.m */; }; 0642E23B1AE0F3D100B820D1 /* STDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F6471E891851CD7C00574E94 /* STDAppDelegate.m */; }; 0642E23C1AE0F3D100B820D1 /* STDropMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63751A59523F00ABD7D3 /* STDropMenuView.m */; }; 0642E23D1AE0F3D100B820D1 /* STWaveBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645F1A59523F00ABD7D3 /* STWaveBarView.m */; }; 0642E23F1AE0F3D100B820D1 /* STASortViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB642B1A59523F00ABD7D3 /* STASortViewController.m */; }; 0642E2401AE0F3D100B820D1 /* STDRecordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645D1A59523F00ABD7D3 /* STDRecordViewController.m */; }; 0642E2411AE0F3D100B820D1 /* STDBaseChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64411A59523F00ABD7D3 /* STDBaseChatCell.m */; }; 0642E2421AE0F3D100B820D1 /* UIBezierPath-Points.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB635B1A59523F00ABD7D3 /* UIBezierPath-Points.m */; }; 0642E2431AE0F3D100B820D1 /* STDImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64381A59523F00ABD7D3 /* STDImage.m */; }; 0642E2441AE0F3D100B820D1 /* STDAbstractFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78C91A822ECF0083D058 /* STDAbstractFactory.m */; }; 0642E2451AE0F3D100B820D1 /* STAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63731A59523F00ABD7D3 /* STAlertView.m */; }; 0642E2461AE0F3D100B820D1 /* STAHanoiView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64201A59523F00ABD7D3 /* STAHanoiView.m */; }; 0642E2471AE0F3D100B820D1 /* STDAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78DA1A8230640083D058 /* STDAdapter.m */; }; 0642E2481AE0F3D100B820D1 /* STDServiceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64611A59523F00ABD7D3 /* STDServiceViewController.m */; }; 0642E2491AE0F3D100B820D1 /* STDCardTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AD21ACEE38C0000E2F8 /* STDCardTransitionDelegate.m */; }; 0642E24A1AE0F3D100B820D1 /* STDTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AC91ACEE09E0000E2F8 /* STDTransitionDelegate.m */; }; 0642E24B1AE0F3D100B820D1 /* STDModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BC51A8BC697000037EF /* STDModel.xcdatamodeld */; }; 0642E24C1AE0F3D100B820D1 /* STDLinkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64161A59523F00ABD7D3 /* STDLinkViewController.m */; }; 0642E24D1AE0F3D100B820D1 /* SCSiriWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64591A59523F00ABD7D3 /* SCSiriWaveformView.m */; }; 0642E24F1AE0F3D100B820D1 /* STDProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78E01A834AF00083D058 /* STDProxy.m */; }; 0642E2501AE0F3D100B820D1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F6471E851851CD7C00574E94 /* main.m */; }; 0642E2511AE0F3D100B820D1 /* STDSideBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63711A59523F00ABD7D3 /* STDSideBarController.m */; }; 0642E2521AE0F3D100B820D1 /* STDReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64311A59523F00ABD7D3 /* STDReaderViewController.m */; }; 0642E2531AE0F3D100B820D1 /* STARootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64241A59523F00ABD7D3 /* STARootViewController.m */; }; 0642E2541AE0F3D100B820D1 /* STDNavigationTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64111A59523F00ABD7D3 /* STDNavigationTestViewController.m */; }; 0642E2551AE0F3D100B820D1 /* STDAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64141A59523F00ABD7D3 /* STDAboutViewController.m */; }; 0642E2561AE0F3D100B820D1 /* STDStartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB647F1A59523F00ABD7D3 /* STDStartViewController.m */; }; 0642E2571AE0F3D100B820D1 /* STDPrototype.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CF1A822ECF0083D058 /* STDPrototype.m */; }; 0642E2581AE0F3D100B820D1 /* STDChat.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64431A59523F00ABD7D3 /* STDChat.m */; }; 0642E2591AE0F3D100B820D1 /* MZCroppableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63591A59523F00ABD7D3 /* MZCroppableView.m */; }; 0642E25A1AE0F3D100B820D1 /* STDBookViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB642F1A59523F00ABD7D3 /* STDBookViewController.m */; }; 0642E25B1AE0F3D100B820D1 /* STDMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643A1A59523F00ABD7D3 /* STDMessage.m */; }; 0642E25C1AE0F3D100B820D1 /* STDImageChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64491A59523F00ABD7D3 /* STDImageChatCell.m */; }; 0642E25D1AE0F3D100B820D1 /* ZYQSphereView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63601A59523F00ABD7D3 /* ZYQSphereView.m */; }; 0642E25E1AE0F3D100B820D1 /* STDChatInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64451A59523F00ABD7D3 /* STDChatInputView.m */; }; 0642E25F1AE0F3D100B820D1 /* STDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640D1A59523F00ABD7D3 /* STDemoViewController.m */; }; 0642E2601AE0F3D100B820D1 /* STDMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB647C1A59523F00ABD7D3 /* STDMapViewController.m */; }; 0642E2611AE0F3D100B820D1 /* STRichView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64331A59523F00ABD7D3 /* STRichView.m */; }; 0642E2621AE0F3D100B820D1 /* SimplePing.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C5185D1AAD4E3F00C2B2E3 /* SimplePing.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 0642E2631AE0F3D100B820D1 /* STDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637D1A59523F00ABD7D3 /* STDViewController.m */; }; 0642E2641AE0F3D100B820D1 /* STDImageBlurViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640F1A59523F00ABD7D3 /* STDImageBlurViewController.m */; }; 0642E2651AE0F3D100B820D1 /* STASortOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64271A59523F00ABD7D3 /* STASortOperation.m */; }; 0642E2661AE0F3D100B820D1 /* STDPingServices.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C518671AAD519900C2B2E3 /* STDPingServices.m */; }; 0642E2671AE0F3D100B820D1 /* STDTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63791A59523F00ABD7D3 /* STDTableViewController.m */; }; 0642E2681AE0F3D100B820D1 /* PFGoldenSectionSpiral.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB635E1A59523F00ABD7D3 /* PFGoldenSectionSpiral.m */; }; 0642E2691AE0F3D100B820D1 /* STDTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63771A59523F00ABD7D3 /* STDTabBarController.m */; }; 0642E26A1AE0F3D100B820D1 /* STDebugFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 067A9F611AADA94B00651433 /* STDebugFoundation.m */; }; 0642E26B1AE0F3D100B820D1 /* STDBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CB1A822ECF0083D058 /* STDBuilder.m */; }; 0642E26E1AE0F3D100B820D1 /* STDownloadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640B1A59523F00ABD7D3 /* STDownloadViewController.m */; }; 0642E26F1AE0F3D100B820D1 /* STACodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB641C1A59523F00ABD7D3 /* STACodeViewController.m */; }; 0642E2701AE0F3D100B820D1 /* STDCardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64011A59523F00ABD7D3 /* STDCardViewController.m */; }; 0642E2711AE0F3D100B820D1 /* STDAboutAudioViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645B1A59523F00ABD7D3 /* STDAboutAudioViewController.m */; }; 0642E2721AE0F3D100B820D1 /* STDChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64471A59523F00ABD7D3 /* STDChatViewController.m */; }; 0642E2731AE0F3D100B820D1 /* STDSingleton.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78D11A822ECF0083D058 /* STDSingleton.m */; }; 0642E2741AE0F3D100B820D1 /* STDFeedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64091A59523F00ABD7D3 /* STDFeedViewController.m */; }; 0642E2751AE0F3D100B820D1 /* STAHanoiViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64221A59523F00ABD7D3 /* STAHanoiViewController.m */; }; 0642E2761AE0F3D100B820D1 /* STDDebugPingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 067A9F5E1AADA73300651433 /* STDDebugPingViewController.m */; }; 0642E2771AE0F3D100B820D1 /* STDFacade.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78DD1A8344C30083D058 /* STDFacade.m */; }; 0642E2781AE0F3D100B820D1 /* STDUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643E1A59523F00ABD7D3 /* STDUser.m */; }; 0642E2791AE0F3D100B820D1 /* STDScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AD51AD3BC3F0000E2F8 /* STDScrollViewController.m */; }; 0642E27A1AE0F3D100B820D1 /* STDTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64181A59523F00ABD7D3 /* STDTextViewController.m */; }; 0642E27B1AE0F3D100B820D1 /* STDBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB88A51A88C8C40082DACA /* STDBridge.m */; }; 0642E27C1AE0F3D100B820D1 /* STDAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 060798F01AC3E68A007C1AA7 /* STDAuthorization.m */; }; 0642E27D1AE0F3D100B820D1 /* STDSettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0664952E1A90C6020026D498 /* STDSettingViewController.m */; }; 0642E27E1AE0F3D100B820D1 /* STDRotateTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758ACF1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m */; }; 0642E27F1AE0F3D100B820D1 /* STDFeedItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64071A59523F00ABD7D3 /* STDFeedItem.m */; }; 0642E2801AE0F3D100B820D1 /* STDFactoryMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CD1A822ECF0083D058 /* STDFactoryMethod.m */; }; 0642E2811AE0F3D100B820D1 /* STASortView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64291A59523F00ABD7D3 /* STASortView.m */; }; 0642E2821AE0F3D100B820D1 /* STDNavigationSettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64781A59523F00ABD7D3 /* STDNavigationSettingViewController.m */; }; 0642E2831AE0F3D100B820D1 /* STDFeedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64031A59523F00ABD7D3 /* STDFeedCell.m */; }; 0642E2841AE0F3D100B820D1 /* STMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637F1A59523F00ABD7D3 /* STMenuView.m */; }; 0642E2851AE0F3D100B820D1 /* STDTextChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB644D1A59523F00ABD7D3 /* STDTextChatCell.m */; }; 0642E2861AE0F3D100B820D1 /* STDFeedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64051A59523F00ABD7D3 /* STDFeedImageView.m */; }; 0642E2871AE0F3D100B820D1 /* STAHanoiOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB641E1A59523F00ABD7D3 /* STAHanoiOperation.m */; }; 0642E2881AE0F3D100B820D1 /* STDRefreshControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 06479D541ACD101E00A44FB9 /* STDRefreshControl.m */; }; 0642E28A1AE0F3D100B820D1 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 065D78E41A8382AC0083D058 /* CFNetwork.framework */; }; 0642E28B1AE0F3D100B820D1 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0698C21C19D1CCE400D0D69A /* WebKit.framework */; }; 0642E28C1AE0F3D100B820D1 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0681CCDA19D3BC9A00D897AF /* Photos.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 0642E28D1AE0F3D100B820D1 /* libstdc++.6.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 06A1CD371978DE3500F68F35 /* libstdc++.6.dylib */; }; 0642E28E1AE0F3D100B820D1 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06A1CD331978DE0700F68F35 /* CoreTelephony.framework */; }; 0642E28F1AE0F3D100B820D1 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06C6F9CD1920F0C10028B2B3 /* CoreLocation.framework */; }; 0642E2901AE0F3D100B820D1 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 06291AE4191F314700EDBD35 /* libxml2.dylib */; }; 0642E2921AE0F3D100B820D1 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F69CFE261873032B00327D8A /* libz.dylib */; }; 0642E2931AE0F3D100B820D1 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6E5B875186413A700FF3408 /* AVFoundation.framework */; }; 0642E2941AE0F3D100B820D1 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6E5B8721864139D00FF3408 /* AudioToolbox.framework */; }; 0642E2951AE0F3D100B820D1 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F66A09E318522F2A002D0597 /* SystemConfiguration.framework */; }; 0642E2961AE0F3D100B820D1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471EE31851CED400574E94 /* QuartzCore.framework */; }; 0642E2971AE0F3D100B820D1 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471EE11851CECF00574E94 /* MapKit.framework */; }; 0642E2981AE0F3D100B820D1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E7B1851CD7C00574E94 /* CoreGraphics.framework */; }; 0642E2991AE0F3D100B820D1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E7D1851CD7C00574E94 /* UIKit.framework */; }; 0642E29A1AE0F3D100B820D1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6471E791851CD7C00574E94 /* Foundation.framework */; }; 0642E29D1AE0F3D100B820D1 /* shangxin_292182.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB5FFF1A594F9900ABD7D3 /* shangxin_292182.jpg */; }; 0642E29E1AE0F3D100B820D1 /* 02@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758AB91ACED7330000E2F8 /* 02@2x.png */; }; 0642E2A01AE0F3D100B820D1 /* 06@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABD1ACED7330000E2F8 /* 06@2x.png */; }; 0642E2A11AE0F3D100B820D1 /* shangxin_292182@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB60001A594F9900ABD7D3 /* shangxin_292182@2x.jpg */; }; 0642E2A31AE0F3D100B820D1 /* chat_image_5.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64531A59523F00ABD7D3 /* chat_image_5.jpg */; }; 0642E2A41AE0F3D100B820D1 /* licenses.html in Resources */ = {isa = PBXBuildFile; fileRef = 066494F91A90AE930026D498 /* licenses.html */; }; 0642E2A51AE0F3D100B820D1 /* chat_image_6.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64541A59523F00ABD7D3 /* chat_image_6.jpg */; }; 0642E2A61AE0F3D100B820D1 /* chat_image_1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB644F1A59523F00ABD7D3 /* chat_image_1.jpg */; }; 0642E2A71AE0F3D100B820D1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F6471E821851CD7C00574E94 /* InfoPlist.strings */; }; 0642E2A81AE0F3D100B820D1 /* chat_image_8.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64561A59523F00ABD7D3 /* chat_image_8.jpg */; }; 0642E2AA1AE0F3D100B820D1 /* chat_image_3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64511A59523F00ABD7D3 /* chat_image_3.jpg */; }; 0642E2AB1AE0F3D100B820D1 /* STDMapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06CB647D1A59523F00ABD7D3 /* STDMapViewController.xib */; }; 0642E2AC1AE0F3D100B820D1 /* book.txt in Resources */ = {isa = PBXBuildFile; fileRef = 06CB642D1A59523F00ABD7D3 /* book.txt */; }; 0642E2AD1AE0F3D100B820D1 /* 01@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758AB81ACED7330000E2F8 /* 01@2x.png */; }; 0642E2AE1AE0F3D100B820D1 /* chat_image_2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64501A59523F00ABD7D3 /* chat_image_2.jpg */; }; 0642E2AF1AE0F3D100B820D1 /* 04@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABB1ACED7330000E2F8 /* 04@2x.png */; }; 0642E2B01AE0F3D100B820D1 /* chat_image_4.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64521A59523F00ABD7D3 /* chat_image_4.jpg */; }; 0642E2B11AE0F3D100B820D1 /* 05@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABC1ACED7330000E2F8 /* 05@2x.png */; }; 0642E2B21AE0F3D100B820D1 /* 08@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABF1ACED7330000E2F8 /* 08@2x.png */; }; 0642E2B31AE0F3D100B820D1 /* 03@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABA1ACED7330000E2F8 /* 03@2x.png */; }; 0642E2B41AE0F3D100B820D1 /* chat_image_7.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64551A59523F00ABD7D3 /* chat_image_7.jpg */; }; 0642E2B51AE0F3D100B820D1 /* 07@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABE1ACED7330000E2F8 /* 07@2x.png */; }; 0642E2B71AE0F3D100B820D1 /* STDNavigationSettingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64791A59523F00ABD7D3 /* STDNavigationSettingViewController.xib */; }; 06479D521ACCF54200A44FB9 /* STDLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06479D511ACCF54200A44FB9 /* STDLoadingView.m */; }; 06479D551ACD101E00A44FB9 /* STDRefreshControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 06479D541ACD101E00A44FB9 /* STDRefreshControl.m */; }; 065B7C911B3FF573006EFEDA /* STDFeedItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64071A59523F00ABD7D3 /* STDFeedItem.m */; }; 065D78D21A822ECF0083D058 /* STDAbstractFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78C91A822ECF0083D058 /* STDAbstractFactory.m */; }; 065D78D31A822ECF0083D058 /* STDBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CB1A822ECF0083D058 /* STDBuilder.m */; }; 065D78D41A822ECF0083D058 /* STDFactoryMethod.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CD1A822ECF0083D058 /* STDFactoryMethod.m */; }; 065D78D51A822ECF0083D058 /* STDPrototype.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78CF1A822ECF0083D058 /* STDPrototype.m */; }; 065D78D61A822ECF0083D058 /* STDSingleton.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78D11A822ECF0083D058 /* STDSingleton.m */; }; 065D78DB1A8230640083D058 /* STDAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78DA1A8230640083D058 /* STDAdapter.m */; }; 065D78DE1A8344C30083D058 /* STDFacade.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78DD1A8344C30083D058 /* STDFacade.m */; }; 065D78E11A834AF00083D058 /* STDProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 065D78E01A834AF00083D058 /* STDProxy.m */; }; 065D78E51A8382AC0083D058 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 065D78E41A8382AC0083D058 /* CFNetwork.framework */; }; 0661EAEF1B8EE94700709CE6 /* STKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0661EAEC1B8EE94700709CE6 /* STKit.framework */; }; 0661EAF01B8EE94700709CE6 /* STKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0661EAEC1B8EE94700709CE6 /* STKit.framework */; }; 0661EAF21B8EE96600709CE6 /* STKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0661EAEC1B8EE94700709CE6 /* STKit.framework */; }; 066494FA1A90AE930026D498 /* licenses.html in Resources */ = {isa = PBXBuildFile; fileRef = 066494F91A90AE930026D498 /* licenses.html */; }; 0664952F1A90C6020026D498 /* STDSettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0664952E1A90C6020026D498 /* STDSettingViewController.m */; }; 06758AC01ACED7330000E2F8 /* 01@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758AB81ACED7330000E2F8 /* 01@2x.png */; }; 06758AC11ACED7330000E2F8 /* 02@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758AB91ACED7330000E2F8 /* 02@2x.png */; }; 06758AC21ACED7330000E2F8 /* 03@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABA1ACED7330000E2F8 /* 03@2x.png */; }; 06758AC31ACED7330000E2F8 /* 04@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABB1ACED7330000E2F8 /* 04@2x.png */; }; 06758AC41ACED7330000E2F8 /* 05@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABC1ACED7330000E2F8 /* 05@2x.png */; }; 06758AC51ACED7330000E2F8 /* 06@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABD1ACED7330000E2F8 /* 06@2x.png */; }; 06758AC61ACED7330000E2F8 /* 07@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABE1ACED7330000E2F8 /* 07@2x.png */; }; 06758AC71ACED7330000E2F8 /* 08@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 06758ABF1ACED7330000E2F8 /* 08@2x.png */; }; 06758ACA1ACEE09E0000E2F8 /* STDTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AC91ACEE09E0000E2F8 /* STDTransitionDelegate.m */; }; 06758AD01ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758ACF1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m */; }; 06758AD31ACEE38C0000E2F8 /* STDCardTransitionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AD21ACEE38C0000E2F8 /* STDCardTransitionDelegate.m */; }; 06758AD61AD3BC3F0000E2F8 /* STDScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06758AD51AD3BC3F0000E2F8 /* STDScrollViewController.m */; }; 067A9F5F1AADA73300651433 /* STDDebugPingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 067A9F5E1AADA73300651433 /* STDDebugPingViewController.m */; }; 067A9F621AADA94B00651433 /* STDebugFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = 067A9F611AADA94B00651433 /* STDebugFoundation.m */; }; 0681CCDB19D3BC9A00D897AF /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0681CCDA19D3BC9A00D897AF /* Photos.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 06A1CD341978DE0700F68F35 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06A1CD331978DE0700F68F35 /* CoreTelephony.framework */; }; 06A1CD381978DE3500F68F35 /* libstdc++.6.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 06A1CD371978DE3500F68F35 /* libstdc++.6.dylib */; }; 06C518601AAD4E3F00C2B2E3 /* SimplePing.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C5185D1AAD4E3F00C2B2E3 /* SimplePing.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 06C518651AAD4E6E00C2B2E3 /* STDLocationPickerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C518641AAD4E6E00C2B2E3 /* STDLocationPickerController.m */; }; 06C518681AAD519900C2B2E3 /* STDPingServices.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C518671AAD519900C2B2E3 /* STDPingServices.m */; }; 06CB60011A594F9900ABD7D3 /* shangxin_292182.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB5FFF1A594F9900ABD7D3 /* shangxin_292182.jpg */; }; 06CB60021A594F9900ABD7D3 /* shangxin_292182@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB60001A594F9900ABD7D3 /* shangxin_292182@2x.jpg */; }; 06CB652F1A59523F00ABD7D3 /* MZCroppableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63591A59523F00ABD7D3 /* MZCroppableView.m */; }; 06CB65301A59523F00ABD7D3 /* UIBezierPath-Points.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB635B1A59523F00ABD7D3 /* UIBezierPath-Points.m */; }; 06CB65311A59523F00ABD7D3 /* PFGoldenSectionSpiral.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB635E1A59523F00ABD7D3 /* PFGoldenSectionSpiral.m */; }; 06CB65321A59523F00ABD7D3 /* ZYQSphereView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63601A59523F00ABD7D3 /* ZYQSphereView.m */; }; 06CB65371A59523F00ABD7D3 /* STDLeftViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB636F1A59523F00ABD7D3 /* STDLeftViewController.m */; }; 06CB65381A59523F00ABD7D3 /* STDSideBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63711A59523F00ABD7D3 /* STDSideBarController.m */; }; 06CB65391A59523F00ABD7D3 /* STAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63731A59523F00ABD7D3 /* STAlertView.m */; }; 06CB653A1A59523F00ABD7D3 /* STDropMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63751A59523F00ABD7D3 /* STDropMenuView.m */; }; 06CB653B1A59523F00ABD7D3 /* STDTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63771A59523F00ABD7D3 /* STDTabBarController.m */; }; 06CB653C1A59523F00ABD7D3 /* STDTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB63791A59523F00ABD7D3 /* STDTableViewController.m */; }; 06CB653D1A59523F00ABD7D3 /* STDTextTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637B1A59523F00ABD7D3 /* STDTextTableViewController.m */; }; 06CB653E1A59523F00ABD7D3 /* STDViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637D1A59523F00ABD7D3 /* STDViewController.m */; }; 06CB653F1A59523F00ABD7D3 /* STMenuView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB637F1A59523F00ABD7D3 /* STMenuView.m */; }; 06CB65A81A59523F00ABD7D3 /* STDCardViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64011A59523F00ABD7D3 /* STDCardViewController.m */; }; 06CB65A91A59523F00ABD7D3 /* STDFeedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64031A59523F00ABD7D3 /* STDFeedCell.m */; }; 06CB65AA1A59523F00ABD7D3 /* STDFeedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64051A59523F00ABD7D3 /* STDFeedImageView.m */; }; 06CB65AC1A59523F00ABD7D3 /* STDFeedViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64091A59523F00ABD7D3 /* STDFeedViewController.m */; }; 06CB65AD1A59523F00ABD7D3 /* STDownloadViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640B1A59523F00ABD7D3 /* STDownloadViewController.m */; }; 06CB65AE1A59523F00ABD7D3 /* STDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640D1A59523F00ABD7D3 /* STDemoViewController.m */; }; 06CB65AF1A59523F00ABD7D3 /* STDImageBlurViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB640F1A59523F00ABD7D3 /* STDImageBlurViewController.m */; }; 06CB65B01A59523F00ABD7D3 /* STDNavigationTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64111A59523F00ABD7D3 /* STDNavigationTestViewController.m */; }; 06CB65B11A59523F00ABD7D3 /* STDAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64141A59523F00ABD7D3 /* STDAboutViewController.m */; }; 06CB65B21A59523F00ABD7D3 /* STDLinkViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64161A59523F00ABD7D3 /* STDLinkViewController.m */; }; 06CB65B31A59523F00ABD7D3 /* STDTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64181A59523F00ABD7D3 /* STDTextViewController.m */; }; 06CB65B41A59523F00ABD7D3 /* STACodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB641C1A59523F00ABD7D3 /* STACodeViewController.m */; }; 06CB65B51A59523F00ABD7D3 /* STAHanoiOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB641E1A59523F00ABD7D3 /* STAHanoiOperation.m */; }; 06CB65B61A59523F00ABD7D3 /* STAHanoiView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64201A59523F00ABD7D3 /* STAHanoiView.m */; }; 06CB65B71A59523F00ABD7D3 /* STAHanoiViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64221A59523F00ABD7D3 /* STAHanoiViewController.m */; }; 06CB65B81A59523F00ABD7D3 /* STARootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64241A59523F00ABD7D3 /* STARootViewController.m */; }; 06CB65B91A59523F00ABD7D3 /* STASortOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64271A59523F00ABD7D3 /* STASortOperation.m */; }; 06CB65BA1A59523F00ABD7D3 /* STASortView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64291A59523F00ABD7D3 /* STASortView.m */; }; 06CB65BB1A59523F00ABD7D3 /* STASortViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB642B1A59523F00ABD7D3 /* STASortViewController.m */; }; 06CB65BC1A59523F00ABD7D3 /* book.txt in Resources */ = {isa = PBXBuildFile; fileRef = 06CB642D1A59523F00ABD7D3 /* book.txt */; }; 06CB65BD1A59523F00ABD7D3 /* STDBookViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB642F1A59523F00ABD7D3 /* STDBookViewController.m */; }; 06CB65BE1A59523F00ABD7D3 /* STDReaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64311A59523F00ABD7D3 /* STDReaderViewController.m */; }; 06CB65BF1A59523F00ABD7D3 /* STRichView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64331A59523F00ABD7D3 /* STRichView.m */; }; 06CB65C01A59523F00ABD7D3 /* STDImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64381A59523F00ABD7D3 /* STDImage.m */; }; 06CB65C11A59523F00ABD7D3 /* STDMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643A1A59523F00ABD7D3 /* STDMessage.m */; }; 06CB65C21A59523F00ABD7D3 /* STDSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643C1A59523F00ABD7D3 /* STDSession.m */; }; 06CB65C31A59523F00ABD7D3 /* STDUser.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB643E1A59523F00ABD7D3 /* STDUser.m */; }; 06CB65C51A59523F00ABD7D3 /* STDBaseChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64411A59523F00ABD7D3 /* STDBaseChatCell.m */; }; 06CB65C61A59523F00ABD7D3 /* STDChat.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64431A59523F00ABD7D3 /* STDChat.m */; }; 06CB65C71A59523F00ABD7D3 /* STDChatInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64451A59523F00ABD7D3 /* STDChatInputView.m */; }; 06CB65C81A59523F00ABD7D3 /* STDChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64471A59523F00ABD7D3 /* STDChatViewController.m */; }; 06CB65C91A59523F00ABD7D3 /* STDImageChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64491A59523F00ABD7D3 /* STDImageChatCell.m */; }; 06CB65CB1A59524000ABD7D3 /* STDTextChatCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB644D1A59523F00ABD7D3 /* STDTextChatCell.m */; }; 06CB65CC1A59524000ABD7D3 /* chat_image_1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB644F1A59523F00ABD7D3 /* chat_image_1.jpg */; }; 06CB65CD1A59524000ABD7D3 /* chat_image_2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64501A59523F00ABD7D3 /* chat_image_2.jpg */; }; 06CB65CE1A59524000ABD7D3 /* chat_image_3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64511A59523F00ABD7D3 /* chat_image_3.jpg */; }; 06CB65CF1A59524000ABD7D3 /* chat_image_4.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64521A59523F00ABD7D3 /* chat_image_4.jpg */; }; 06CB65D01A59524000ABD7D3 /* chat_image_5.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64531A59523F00ABD7D3 /* chat_image_5.jpg */; }; 06CB65D11A59524000ABD7D3 /* chat_image_6.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64541A59523F00ABD7D3 /* chat_image_6.jpg */; }; 06CB65D21A59524000ABD7D3 /* chat_image_7.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64551A59523F00ABD7D3 /* chat_image_7.jpg */; }; 06CB65D31A59524000ABD7D3 /* chat_image_8.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64561A59523F00ABD7D3 /* chat_image_8.jpg */; }; 06CB65D41A59524000ABD7D3 /* SCSiriWaveformView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64591A59523F00ABD7D3 /* SCSiriWaveformView.m */; }; 06CB65D51A59524000ABD7D3 /* STDAboutAudioViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645B1A59523F00ABD7D3 /* STDAboutAudioViewController.m */; }; 06CB65D61A59524000ABD7D3 /* STDRecordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645D1A59523F00ABD7D3 /* STDRecordViewController.m */; }; 06CB65D71A59524000ABD7D3 /* STWaveBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB645F1A59523F00ABD7D3 /* STWaveBarView.m */; }; 06CB65D81A59524000ABD7D3 /* STDServiceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64611A59523F00ABD7D3 /* STDServiceViewController.m */; }; 06CB65E21A59524000ABD7D3 /* STDMoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64761A59523F00ABD7D3 /* STDMoreViewController.m */; }; 06CB65E31A59524000ABD7D3 /* STDNavigationSettingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB64781A59523F00ABD7D3 /* STDNavigationSettingViewController.m */; }; 06CB65E41A59524000ABD7D3 /* STDNavigationSettingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06CB64791A59523F00ABD7D3 /* STDNavigationSettingViewController.xib */; }; 06CB65E51A59524000ABD7D3 /* STDMapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB647C1A59523F00ABD7D3 /* STDMapViewController.m */; }; 06CB65E61A59524000ABD7D3 /* STDMapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06CB647D1A59523F00ABD7D3 /* STDMapViewController.xib */; }; 06CB65E71A59524000ABD7D3 /* STDStartViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB647F1A59523F00ABD7D3 /* STDStartViewController.m */; }; 06CB88A61A88C8C40082DACA /* STDBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CB88A51A88C8C40082DACA /* STDBridge.m */; }; 06CF9BC71A8BC697000037EF /* STDModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BC51A8BC697000037EF /* STDModel.xcdatamodeld */; }; 06CF9BD21A8BD2A3000037EF /* STDAbstractFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BCC1A8BD2A3000037EF /* STDAbstractFactoryTests.m */; }; 06CF9BD31A8BD2A3000037EF /* STDFactoryMethodTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BCD1A8BD2A3000037EF /* STDFactoryMethodTests.m */; }; 06CF9BD41A8BD2A3000037EF /* STDSingletonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BCE1A8BD2A3000037EF /* STDSingletonTests.m */; }; 06CF9BD61A8BD2A3000037EF /* STKitDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 06CF9BD11A8BD2A3000037EF /* STKitDemoTests.m */; }; 06CFCBBF1A676F39003DDC93 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0698C21C19D1CCE400D0D69A /* WebKit.framework */; }; 06DD3BF81B79CB6C002FA2B6 /* STDCoreDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 06DD3BF71B79CB6C002FA2B6 /* STDCoreDataManager.m */; }; 06DD3BF91B79CB6C002FA2B6 /* STDCoreDataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 06DD3BF71B79CB6C002FA2B6 /* STDCoreDataManager.m */; }; 06E0FED41C3288A500D1022A /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FED31C3288A500D1022A /* Accelerate.framework */; }; 06E0FED51C3288CD00D1022A /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FED31C3288A500D1022A /* Accelerate.framework */; }; 06E0FED61C328ACD00D1022A /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FED11C32889700D1022A /* ImageIO.framework */; }; 06E0FED71C328AD300D1022A /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FED11C32889700D1022A /* ImageIO.framework */; }; 06E0FED91C328B0300D1022A /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FED81C328B0300D1022A /* CoreImage.framework */; }; 06E0FEDB1C328B2500D1022A /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FEDA1C328B2500D1022A /* MobileCoreServices.framework */; }; 06E0FEDC1C328C7000D1022A /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06E0FEDA1C328B2500D1022A /* MobileCoreServices.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ 06CF9BB21A8BB802000037EF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F6471E6E1851CD7C00574E94 /* Project object */; proxyType = 1; remoteGlobalIDString = 0602B48E196974150004ACBB; remoteInfo = STKitDemo; }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ 0642E2D71AE0F51A00B820D1 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; }; 069586EA1AE5FF6100F149F1 /* Embed App Extensions */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 13; files = ( ); name = "Embed App Extensions"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 0602B51B196974150004ACBB /* STKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 060798EF1AC3E68A007C1AA7 /* STDAuthorization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDAuthorization.h; sourceTree = ""; }; 060798F01AC3E68A007C1AA7 /* STDAuthorization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAuthorization.m; sourceTree = ""; }; 06291AE4191F314700EDBD35 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; }; 0634101A19C9EBE3003BC34E /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; 0642E2BD1AE0F3D100B820D1 /* STKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = STKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0642E2BF1AE0F45D00B820D1 /* STKitDemoInHouse-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "STKitDemoInHouse-Info.plist"; sourceTree = ""; }; 06479D501ACCF54200A44FB9 /* STDLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDLoadingView.h; sourceTree = ""; }; 06479D511ACCF54200A44FB9 /* STDLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDLoadingView.m; sourceTree = ""; }; 06479D531ACD101E00A44FB9 /* STDRefreshControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDRefreshControl.h; sourceTree = ""; }; 06479D541ACD101E00A44FB9 /* STDRefreshControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDRefreshControl.m; sourceTree = ""; }; 065D787D1A80C3BB0083D058 /* STDesignPatterns.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDesignPatterns.h; sourceTree = ""; }; 065D78B61A81ECB60083D058 /* STDScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDScrollViewController.h; sourceTree = ""; }; 065D78B71A81ECB60083D058 /* STDScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDScrollViewController.m; sourceTree = ""; }; 065D78C81A822ECF0083D058 /* STDAbstractFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDAbstractFactory.h; sourceTree = ""; }; 065D78C91A822ECF0083D058 /* STDAbstractFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAbstractFactory.m; sourceTree = ""; }; 065D78CA1A822ECF0083D058 /* STDBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDBuilder.h; sourceTree = ""; }; 065D78CB1A822ECF0083D058 /* STDBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDBuilder.m; sourceTree = ""; }; 065D78CC1A822ECF0083D058 /* STDFactoryMethod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFactoryMethod.h; sourceTree = ""; }; 065D78CD1A822ECF0083D058 /* STDFactoryMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFactoryMethod.m; sourceTree = ""; }; 065D78CE1A822ECF0083D058 /* STDPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDPrototype.h; sourceTree = ""; }; 065D78CF1A822ECF0083D058 /* STDPrototype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDPrototype.m; sourceTree = ""; }; 065D78D01A822ECF0083D058 /* STDSingleton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDSingleton.h; sourceTree = ""; }; 065D78D11A822ECF0083D058 /* STDSingleton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDSingleton.m; sourceTree = ""; }; 065D78D91A8230640083D058 /* STDAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDAdapter.h; sourceTree = ""; }; 065D78DA1A8230640083D058 /* STDAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAdapter.m; sourceTree = ""; }; 065D78DC1A8344C30083D058 /* STDFacade.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFacade.h; sourceTree = ""; }; 065D78DD1A8344C30083D058 /* STDFacade.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFacade.m; sourceTree = ""; }; 065D78DF1A834AF00083D058 /* STDProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDProxy.h; sourceTree = ""; }; 065D78E01A834AF00083D058 /* STDProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDProxy.m; sourceTree = ""; }; 065D78E41A8382AC0083D058 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 0661EAEC1B8EE94700709CE6 /* STKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = STKit.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator/STKit.framework"; sourceTree = ""; }; 066494F91A90AE930026D498 /* licenses.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = licenses.html; sourceTree = ""; }; 0664952D1A90C6020026D498 /* STDSettingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDSettingViewController.h; sourceTree = ""; }; 0664952E1A90C6020026D498 /* STDSettingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDSettingViewController.m; sourceTree = ""; }; 06758AB81ACED7330000E2F8 /* 01@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "01@2x.png"; sourceTree = ""; }; 06758AB91ACED7330000E2F8 /* 02@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "02@2x.png"; sourceTree = ""; }; 06758ABA1ACED7330000E2F8 /* 03@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "03@2x.png"; sourceTree = ""; }; 06758ABB1ACED7330000E2F8 /* 04@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "04@2x.png"; sourceTree = ""; }; 06758ABC1ACED7330000E2F8 /* 05@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "05@2x.png"; sourceTree = ""; }; 06758ABD1ACED7330000E2F8 /* 06@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "06@2x.png"; sourceTree = ""; }; 06758ABE1ACED7330000E2F8 /* 07@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "07@2x.png"; sourceTree = ""; }; 06758ABF1ACED7330000E2F8 /* 08@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "08@2x.png"; sourceTree = ""; }; 06758AC81ACEE09E0000E2F8 /* STDTransitionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTransitionDelegate.h; sourceTree = ""; }; 06758AC91ACEE09E0000E2F8 /* STDTransitionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTransitionDelegate.m; sourceTree = ""; }; 06758ACE1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDRotateTransitionDelegate.h; sourceTree = ""; }; 06758ACF1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDRotateTransitionDelegate.m; sourceTree = ""; }; 06758AD11ACEE38C0000E2F8 /* STDCardTransitionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDCardTransitionDelegate.h; sourceTree = ""; }; 06758AD21ACEE38C0000E2F8 /* STDCardTransitionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDCardTransitionDelegate.m; sourceTree = ""; }; 06758AD41AD3BC3F0000E2F8 /* STDScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDScrollViewController.h; sourceTree = ""; }; 06758AD51AD3BC3F0000E2F8 /* STDScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDScrollViewController.m; sourceTree = ""; }; 067A9F5D1AADA73300651433 /* STDDebugPingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDDebugPingViewController.h; sourceTree = ""; }; 067A9F5E1AADA73300651433 /* STDDebugPingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDDebugPingViewController.m; sourceTree = ""; }; 067A9F601AADA94B00651433 /* STDebugFoundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDebugFoundation.h; sourceTree = ""; }; 067A9F611AADA94B00651433 /* STDebugFoundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDebugFoundation.m; sourceTree = ""; }; 0681CCDA19D3BC9A00D897AF /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; 0698C21C19D1CCE400D0D69A /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 06A1CD331978DE0700F68F35 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; 06A1CD351978DE1400F68F35 /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "usr/lib/libstdc++.dylib"; sourceTree = SDKROOT; }; 06A1CD371978DE3500F68F35 /* libstdc++.6.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.6.dylib"; path = "usr/lib/libstdc++.6.dylib"; sourceTree = SDKROOT; }; 06A4D3BF19E6B3C7007D332D /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; }; 06A4D46719E80498007D332D /* STKitDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = STKitDemo.entitlements; sourceTree = ""; }; 06BE56D01A0404CF00FBC4C8 /* STDemoImages.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = STDemoImages.xcassets; sourceTree = ""; }; 06C5185C1AAD4E3F00C2B2E3 /* SimplePing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimplePing.h; sourceTree = ""; }; 06C5185D1AAD4E3F00C2B2E3 /* SimplePing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimplePing.m; sourceTree = ""; }; 06C518631AAD4E6E00C2B2E3 /* STDLocationPickerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDLocationPickerController.h; sourceTree = ""; }; 06C518641AAD4E6E00C2B2E3 /* STDLocationPickerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDLocationPickerController.m; sourceTree = ""; }; 06C518661AAD519900C2B2E3 /* STDPingServices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDPingServices.h; sourceTree = ""; }; 06C518671AAD519900C2B2E3 /* STDPingServices.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDPingServices.m; sourceTree = ""; }; 06C6F9CD1920F0C10028B2B3 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 06CB5FFF1A594F9900ABD7D3 /* shangxin_292182.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = shangxin_292182.jpg; sourceTree = ""; }; 06CB60001A594F9900ABD7D3 /* shangxin_292182@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "shangxin_292182@2x.jpg"; sourceTree = ""; }; 06CB63581A59523F00ABD7D3 /* MZCroppableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MZCroppableView.h; sourceTree = ""; }; 06CB63591A59523F00ABD7D3 /* MZCroppableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MZCroppableView.m; sourceTree = ""; }; 06CB635A1A59523F00ABD7D3 /* UIBezierPath-Points.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIBezierPath-Points.h"; sourceTree = ""; }; 06CB635B1A59523F00ABD7D3 /* UIBezierPath-Points.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIBezierPath-Points.m"; sourceTree = ""; }; 06CB635D1A59523F00ABD7D3 /* PFGoldenSectionSpiral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFGoldenSectionSpiral.h; sourceTree = ""; }; 06CB635E1A59523F00ABD7D3 /* PFGoldenSectionSpiral.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFGoldenSectionSpiral.m; sourceTree = ""; }; 06CB635F1A59523F00ABD7D3 /* ZYQSphereView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZYQSphereView.h; sourceTree = ""; }; 06CB63601A59523F00ABD7D3 /* ZYQSphereView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZYQSphereView.m; sourceTree = ""; }; 06CB636E1A59523F00ABD7D3 /* STDLeftViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDLeftViewController.h; sourceTree = ""; }; 06CB636F1A59523F00ABD7D3 /* STDLeftViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDLeftViewController.m; sourceTree = ""; }; 06CB63701A59523F00ABD7D3 /* STDSideBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDSideBarController.h; sourceTree = ""; }; 06CB63711A59523F00ABD7D3 /* STDSideBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDSideBarController.m; sourceTree = ""; }; 06CB63721A59523F00ABD7D3 /* STAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STAlertView.h; sourceTree = ""; }; 06CB63731A59523F00ABD7D3 /* STAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STAlertView.m; sourceTree = ""; }; 06CB63741A59523F00ABD7D3 /* STDropMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDropMenuView.h; sourceTree = ""; }; 06CB63751A59523F00ABD7D3 /* STDropMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDropMenuView.m; sourceTree = ""; }; 06CB63761A59523F00ABD7D3 /* STDTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTabBarController.h; sourceTree = ""; }; 06CB63771A59523F00ABD7D3 /* STDTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTabBarController.m; sourceTree = ""; }; 06CB63781A59523F00ABD7D3 /* STDTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTableViewController.h; sourceTree = ""; }; 06CB63791A59523F00ABD7D3 /* STDTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTableViewController.m; sourceTree = ""; }; 06CB637A1A59523F00ABD7D3 /* STDTextTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTextTableViewController.h; sourceTree = ""; }; 06CB637B1A59523F00ABD7D3 /* STDTextTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTextTableViewController.m; sourceTree = ""; }; 06CB637C1A59523F00ABD7D3 /* STDViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDViewController.h; sourceTree = ""; }; 06CB637D1A59523F00ABD7D3 /* STDViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDViewController.m; sourceTree = ""; }; 06CB637E1A59523F00ABD7D3 /* STMenuView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMenuView.h; sourceTree = ""; }; 06CB637F1A59523F00ABD7D3 /* STMenuView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STMenuView.m; sourceTree = ""; }; 06CB64001A59523F00ABD7D3 /* STDCardViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDCardViewController.h; sourceTree = ""; }; 06CB64011A59523F00ABD7D3 /* STDCardViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDCardViewController.m; sourceTree = ""; }; 06CB64021A59523F00ABD7D3 /* STDFeedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFeedCell.h; sourceTree = ""; }; 06CB64031A59523F00ABD7D3 /* STDFeedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFeedCell.m; sourceTree = ""; }; 06CB64041A59523F00ABD7D3 /* STDFeedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFeedImageView.h; sourceTree = ""; }; 06CB64051A59523F00ABD7D3 /* STDFeedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFeedImageView.m; sourceTree = ""; }; 06CB64061A59523F00ABD7D3 /* STDFeedItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFeedItem.h; sourceTree = ""; }; 06CB64071A59523F00ABD7D3 /* STDFeedItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFeedItem.m; sourceTree = ""; }; 06CB64081A59523F00ABD7D3 /* STDFeedViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDFeedViewController.h; sourceTree = ""; }; 06CB64091A59523F00ABD7D3 /* STDFeedViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFeedViewController.m; sourceTree = ""; }; 06CB640A1A59523F00ABD7D3 /* STDownloadViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDownloadViewController.h; sourceTree = ""; }; 06CB640B1A59523F00ABD7D3 /* STDownloadViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDownloadViewController.m; sourceTree = ""; }; 06CB640C1A59523F00ABD7D3 /* STDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDemoViewController.h; sourceTree = ""; }; 06CB640D1A59523F00ABD7D3 /* STDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDemoViewController.m; sourceTree = ""; }; 06CB640E1A59523F00ABD7D3 /* STDImageBlurViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDImageBlurViewController.h; sourceTree = ""; }; 06CB640F1A59523F00ABD7D3 /* STDImageBlurViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDImageBlurViewController.m; sourceTree = ""; }; 06CB64101A59523F00ABD7D3 /* STDNavigationTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDNavigationTestViewController.h; sourceTree = ""; }; 06CB64111A59523F00ABD7D3 /* STDNavigationTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDNavigationTestViewController.m; sourceTree = ""; }; 06CB64131A59523F00ABD7D3 /* STDAboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDAboutViewController.h; sourceTree = ""; }; 06CB64141A59523F00ABD7D3 /* STDAboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAboutViewController.m; sourceTree = ""; }; 06CB64151A59523F00ABD7D3 /* STDLinkViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDLinkViewController.h; sourceTree = ""; }; 06CB64161A59523F00ABD7D3 /* STDLinkViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDLinkViewController.m; sourceTree = ""; }; 06CB64171A59523F00ABD7D3 /* STDTextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTextViewController.h; sourceTree = ""; }; 06CB64181A59523F00ABD7D3 /* STDTextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTextViewController.m; sourceTree = ""; }; 06CB641B1A59523F00ABD7D3 /* STACodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STACodeViewController.h; sourceTree = ""; }; 06CB641C1A59523F00ABD7D3 /* STACodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STACodeViewController.m; sourceTree = ""; }; 06CB641D1A59523F00ABD7D3 /* STAHanoiOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STAHanoiOperation.h; sourceTree = ""; }; 06CB641E1A59523F00ABD7D3 /* STAHanoiOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STAHanoiOperation.m; sourceTree = ""; }; 06CB641F1A59523F00ABD7D3 /* STAHanoiView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STAHanoiView.h; sourceTree = ""; }; 06CB64201A59523F00ABD7D3 /* STAHanoiView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STAHanoiView.m; sourceTree = ""; }; 06CB64211A59523F00ABD7D3 /* STAHanoiViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STAHanoiViewController.h; sourceTree = ""; }; 06CB64221A59523F00ABD7D3 /* STAHanoiViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STAHanoiViewController.m; sourceTree = ""; }; 06CB64231A59523F00ABD7D3 /* STARootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STARootViewController.h; sourceTree = ""; }; 06CB64241A59523F00ABD7D3 /* STARootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STARootViewController.m; sourceTree = ""; }; 06CB64251A59523F00ABD7D3 /* STASortDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STASortDefines.h; sourceTree = ""; }; 06CB64261A59523F00ABD7D3 /* STASortOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STASortOperation.h; sourceTree = ""; }; 06CB64271A59523F00ABD7D3 /* STASortOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STASortOperation.m; sourceTree = ""; }; 06CB64281A59523F00ABD7D3 /* STASortView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STASortView.h; sourceTree = ""; }; 06CB64291A59523F00ABD7D3 /* STASortView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STASortView.m; sourceTree = ""; }; 06CB642A1A59523F00ABD7D3 /* STASortViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STASortViewController.h; sourceTree = ""; }; 06CB642B1A59523F00ABD7D3 /* STASortViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STASortViewController.m; sourceTree = ""; }; 06CB642D1A59523F00ABD7D3 /* book.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = book.txt; sourceTree = ""; }; 06CB642E1A59523F00ABD7D3 /* STDBookViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDBookViewController.h; sourceTree = ""; }; 06CB642F1A59523F00ABD7D3 /* STDBookViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDBookViewController.m; sourceTree = ""; }; 06CB64301A59523F00ABD7D3 /* STDReaderViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDReaderViewController.h; sourceTree = ""; }; 06CB64311A59523F00ABD7D3 /* STDReaderViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDReaderViewController.m; sourceTree = ""; }; 06CB64321A59523F00ABD7D3 /* STRichView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STRichView.h; sourceTree = ""; }; 06CB64331A59523F00ABD7D3 /* STRichView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STRichView.m; sourceTree = ""; }; 06CB64361A59523F00ABD7D3 /* STDEntityDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDEntityDefines.h; sourceTree = ""; }; 06CB64371A59523F00ABD7D3 /* STDImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDImage.h; sourceTree = ""; }; 06CB64381A59523F00ABD7D3 /* STDImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDImage.m; sourceTree = ""; }; 06CB64391A59523F00ABD7D3 /* STDMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDMessage.h; sourceTree = ""; }; 06CB643A1A59523F00ABD7D3 /* STDMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDMessage.m; sourceTree = ""; }; 06CB643B1A59523F00ABD7D3 /* STDSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDSession.h; sourceTree = ""; }; 06CB643C1A59523F00ABD7D3 /* STDSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDSession.m; sourceTree = ""; }; 06CB643D1A59523F00ABD7D3 /* STDUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDUser.h; sourceTree = ""; }; 06CB643E1A59523F00ABD7D3 /* STDUser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDUser.m; sourceTree = ""; }; 06CB64401A59523F00ABD7D3 /* STDBaseChatCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDBaseChatCell.h; sourceTree = ""; }; 06CB64411A59523F00ABD7D3 /* STDBaseChatCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDBaseChatCell.m; sourceTree = ""; }; 06CB64421A59523F00ABD7D3 /* STDChat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDChat.h; sourceTree = ""; }; 06CB64431A59523F00ABD7D3 /* STDChat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDChat.m; sourceTree = ""; }; 06CB64441A59523F00ABD7D3 /* STDChatInputView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDChatInputView.h; sourceTree = ""; }; 06CB64451A59523F00ABD7D3 /* STDChatInputView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDChatInputView.m; sourceTree = ""; }; 06CB64461A59523F00ABD7D3 /* STDChatViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDChatViewController.h; sourceTree = ""; }; 06CB64471A59523F00ABD7D3 /* STDChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDChatViewController.m; sourceTree = ""; }; 06CB64481A59523F00ABD7D3 /* STDImageChatCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDImageChatCell.h; sourceTree = ""; }; 06CB64491A59523F00ABD7D3 /* STDImageChatCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDImageChatCell.m; sourceTree = ""; }; 06CB644C1A59523F00ABD7D3 /* STDTextChatCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDTextChatCell.h; sourceTree = ""; }; 06CB644D1A59523F00ABD7D3 /* STDTextChatCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDTextChatCell.m; sourceTree = ""; }; 06CB644F1A59523F00ABD7D3 /* chat_image_1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_1.jpg; sourceTree = ""; }; 06CB64501A59523F00ABD7D3 /* chat_image_2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_2.jpg; sourceTree = ""; }; 06CB64511A59523F00ABD7D3 /* chat_image_3.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_3.jpg; sourceTree = ""; }; 06CB64521A59523F00ABD7D3 /* chat_image_4.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_4.jpg; sourceTree = ""; }; 06CB64531A59523F00ABD7D3 /* chat_image_5.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_5.jpg; sourceTree = ""; }; 06CB64541A59523F00ABD7D3 /* chat_image_6.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_6.jpg; sourceTree = ""; }; 06CB64551A59523F00ABD7D3 /* chat_image_7.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_7.jpg; sourceTree = ""; }; 06CB64561A59523F00ABD7D3 /* chat_image_8.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chat_image_8.jpg; sourceTree = ""; }; 06CB64581A59523F00ABD7D3 /* SCSiriWaveformView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCSiriWaveformView.h; sourceTree = ""; }; 06CB64591A59523F00ABD7D3 /* SCSiriWaveformView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SCSiriWaveformView.m; sourceTree = ""; }; 06CB645A1A59523F00ABD7D3 /* STDAboutAudioViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDAboutAudioViewController.h; sourceTree = ""; }; 06CB645B1A59523F00ABD7D3 /* STDAboutAudioViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAboutAudioViewController.m; sourceTree = ""; }; 06CB645C1A59523F00ABD7D3 /* STDRecordViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDRecordViewController.h; sourceTree = ""; }; 06CB645D1A59523F00ABD7D3 /* STDRecordViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDRecordViewController.m; sourceTree = ""; }; 06CB645E1A59523F00ABD7D3 /* STWaveBarView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STWaveBarView.h; sourceTree = ""; }; 06CB645F1A59523F00ABD7D3 /* STWaveBarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STWaveBarView.m; sourceTree = ""; }; 06CB64601A59523F00ABD7D3 /* STDServiceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDServiceViewController.h; sourceTree = ""; }; 06CB64611A59523F00ABD7D3 /* STDServiceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDServiceViewController.m; sourceTree = ""; }; 06CB64751A59523F00ABD7D3 /* STDMoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDMoreViewController.h; sourceTree = ""; }; 06CB64761A59523F00ABD7D3 /* STDMoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDMoreViewController.m; sourceTree = ""; }; 06CB64771A59523F00ABD7D3 /* STDNavigationSettingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDNavigationSettingViewController.h; sourceTree = ""; }; 06CB64781A59523F00ABD7D3 /* STDNavigationSettingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDNavigationSettingViewController.m; sourceTree = ""; }; 06CB64791A59523F00ABD7D3 /* STDNavigationSettingViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = STDNavigationSettingViewController.xib; sourceTree = ""; }; 06CB647B1A59523F00ABD7D3 /* STDMapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDMapViewController.h; sourceTree = ""; }; 06CB647C1A59523F00ABD7D3 /* STDMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDMapViewController.m; sourceTree = ""; }; 06CB647D1A59523F00ABD7D3 /* STDMapViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = STDMapViewController.xib; sourceTree = ""; }; 06CB647E1A59523F00ABD7D3 /* STDStartViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDStartViewController.h; sourceTree = ""; }; 06CB647F1A59523F00ABD7D3 /* STDStartViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDStartViewController.m; sourceTree = ""; }; 06CB88A41A88C8C40082DACA /* STDBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDBridge.h; sourceTree = ""; }; 06CB88A51A88C8C40082DACA /* STDBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDBridge.m; sourceTree = ""; }; 06CF9BAC1A8BB802000037EF /* STKitDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = STKitDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 06CF9BC61A8BC697000037EF /* STDModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = STDModel.xcdatamodel; sourceTree = ""; }; 06CF9BC81A8BC6B0000037EF /* STDModel 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "STDModel 2.xcdatamodel"; sourceTree = ""; }; 06CF9BCC1A8BD2A3000037EF /* STDAbstractFactoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDAbstractFactoryTests.m; sourceTree = ""; }; 06CF9BCD1A8BD2A3000037EF /* STDFactoryMethodTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDFactoryMethodTests.m; sourceTree = ""; }; 06CF9BCE1A8BD2A3000037EF /* STDSingletonTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDSingletonTests.m; sourceTree = ""; }; 06CF9BD01A8BD2A3000037EF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 06CF9BD11A8BD2A3000037EF /* STKitDemoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STKitDemoTests.m; sourceTree = ""; }; 06CFCB9C1A63973C003DDC93 /* SpriteKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SpriteKit.framework; path = System/Library/Frameworks/SpriteKit.framework; sourceTree = SDKROOT; }; 06DBF9E019F8CFBB009ECABA /* Social.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Social.framework; path = System/Library/Frameworks/Social.framework; sourceTree = SDKROOT; }; 06DD3BF61B79CB6C002FA2B6 /* STDCoreDataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STDCoreDataManager.h; sourceTree = ""; }; 06DD3BF71B79CB6C002FA2B6 /* STDCoreDataManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = STDCoreDataManager.m; sourceTree = ""; }; 06E0FED11C32889700D1022A /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; 06E0FED31C3288A500D1022A /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 06E0FED81C328B0300D1022A /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; 06E0FEDA1C328B2500D1022A /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; F6471E791851CD7C00574E94 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; F6471E7B1851CD7C00574E94 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; F6471E7D1851CD7C00574E94 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; F6471E811851CD7C00574E94 /* STKitDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "STKitDemo-Info.plist"; sourceTree = ""; }; F6471E831851CD7C00574E94 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; F6471E851851CD7C00574E94 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; F6471E871851CD7C00574E94 /* STKitDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "STKitDemo-Prefix.pch"; sourceTree = ""; }; F6471E881851CD7C00574E94 /* STDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = STDAppDelegate.h; sourceTree = ""; }; F6471E891851CD7C00574E94 /* STDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = STDAppDelegate.m; sourceTree = ""; }; F6471EE11851CECF00574E94 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; F6471EE31851CED400574E94 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; F66A09E318522F2A002D0597 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; F69CFE261873032B00327D8A /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; F6E5B8721864139D00FF3408 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; F6E5B875186413A700FF3408 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 0602B4F5196974150004ACBB /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 06E0FEDB1C328B2500D1022A /* MobileCoreServices.framework in Frameworks */, 06E0FED91C328B0300D1022A /* CoreImage.framework in Frameworks */, 06E0FED71C328AD300D1022A /* ImageIO.framework in Frameworks */, 06E0FED41C3288A500D1022A /* Accelerate.framework in Frameworks */, 065D78E51A8382AC0083D058 /* CFNetwork.framework in Frameworks */, 06CFCBBF1A676F39003DDC93 /* WebKit.framework in Frameworks */, 0681CCDB19D3BC9A00D897AF /* Photos.framework in Frameworks */, 06A1CD381978DE3500F68F35 /* libstdc++.6.dylib in Frameworks */, 06A1CD341978DE0700F68F35 /* CoreTelephony.framework in Frameworks */, 0602B4F6196974150004ACBB /* CoreLocation.framework in Frameworks */, 0602B4F7196974150004ACBB /* libxml2.dylib in Frameworks */, 0602B4F9196974150004ACBB /* libz.dylib in Frameworks */, 0602B4FA196974150004ACBB /* AVFoundation.framework in Frameworks */, 0602B4FB196974150004ACBB /* AudioToolbox.framework in Frameworks */, 0602B4FC196974150004ACBB /* SystemConfiguration.framework in Frameworks */, 0602B4FE196974150004ACBB /* QuartzCore.framework in Frameworks */, 0602B4FF196974150004ACBB /* MapKit.framework in Frameworks */, 0602B500196974150004ACBB /* CoreGraphics.framework in Frameworks */, 0661EAF21B8EE96600709CE6 /* STKit.framework in Frameworks */, 0602B501196974150004ACBB /* UIKit.framework in Frameworks */, 0602B503196974150004ACBB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 0642E2891AE0F3D100B820D1 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 06E0FED61C328ACD00D1022A /* ImageIO.framework in Frameworks */, 06E0FEDC1C328C7000D1022A /* MobileCoreServices.framework in Frameworks */, 06E0FED51C3288CD00D1022A /* Accelerate.framework in Frameworks */, 0642E28A1AE0F3D100B820D1 /* CFNetwork.framework in Frameworks */, 0642E28B1AE0F3D100B820D1 /* WebKit.framework in Frameworks */, 0642E28C1AE0F3D100B820D1 /* Photos.framework in Frameworks */, 0642E28D1AE0F3D100B820D1 /* libstdc++.6.dylib in Frameworks */, 0642E28E1AE0F3D100B820D1 /* CoreTelephony.framework in Frameworks */, 0642E28F1AE0F3D100B820D1 /* CoreLocation.framework in Frameworks */, 0642E2901AE0F3D100B820D1 /* libxml2.dylib in Frameworks */, 0642E2921AE0F3D100B820D1 /* libz.dylib in Frameworks */, 0642E2931AE0F3D100B820D1 /* AVFoundation.framework in Frameworks */, 0642E2941AE0F3D100B820D1 /* AudioToolbox.framework in Frameworks */, 0642E2951AE0F3D100B820D1 /* SystemConfiguration.framework in Frameworks */, 0642E2961AE0F3D100B820D1 /* QuartzCore.framework in Frameworks */, 0642E2971AE0F3D100B820D1 /* MapKit.framework in Frameworks */, 0642E2981AE0F3D100B820D1 /* CoreGraphics.framework in Frameworks */, 0661EAF01B8EE94700709CE6 /* STKit.framework in Frameworks */, 0642E2991AE0F3D100B820D1 /* UIKit.framework in Frameworks */, 0642E29A1AE0F3D100B820D1 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; 06CF9BA91A8BB802000037EF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 0661EAEF1B8EE94700709CE6 /* STKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 065D78791A80C0AC0083D058 /* DesignPatterns */ = { isa = PBXGroup; children = ( 065D787D1A80C3BB0083D058 /* STDesignPatterns.h */, 065D78C71A822ECF0083D058 /* Creational */, 065D78D71A822FA50083D058 /* Structural */, 065D78D81A822FEC0083D058 /* Behavioral */, ); path = DesignPatterns; sourceTree = ""; }; 065D78C71A822ECF0083D058 /* Creational */ = { isa = PBXGroup; children = ( 065D78CC1A822ECF0083D058 /* STDFactoryMethod.h */, 065D78CD1A822ECF0083D058 /* STDFactoryMethod.m */, 065D78C81A822ECF0083D058 /* STDAbstractFactory.h */, 065D78C91A822ECF0083D058 /* STDAbstractFactory.m */, 065D78CA1A822ECF0083D058 /* STDBuilder.h */, 065D78CB1A822ECF0083D058 /* STDBuilder.m */, 065D78CE1A822ECF0083D058 /* STDPrototype.h */, 065D78CF1A822ECF0083D058 /* STDPrototype.m */, 065D78D01A822ECF0083D058 /* STDSingleton.h */, 065D78D11A822ECF0083D058 /* STDSingleton.m */, ); path = Creational; sourceTree = ""; }; 065D78D71A822FA50083D058 /* Structural */ = { isa = PBXGroup; children = ( 065D78D91A8230640083D058 /* STDAdapter.h */, 065D78DA1A8230640083D058 /* STDAdapter.m */, 065D78DC1A8344C30083D058 /* STDFacade.h */, 065D78DD1A8344C30083D058 /* STDFacade.m */, 065D78DF1A834AF00083D058 /* STDProxy.h */, 065D78E01A834AF00083D058 /* STDProxy.m */, 06CB88A41A88C8C40082DACA /* STDBridge.h */, 06CB88A51A88C8C40082DACA /* STDBridge.m */, ); path = Structural; sourceTree = ""; }; 065D78D81A822FEC0083D058 /* Behavioral */ = { isa = PBXGroup; children = ( ); path = Behavioral; sourceTree = ""; }; 06758AB71ACED7330000E2F8 /* STDLoading */ = { isa = PBXGroup; children = ( 06758AB81ACED7330000E2F8 /* 01@2x.png */, 06758AB91ACED7330000E2F8 /* 02@2x.png */, 06758ABA1ACED7330000E2F8 /* 03@2x.png */, 06758ABB1ACED7330000E2F8 /* 04@2x.png */, 06758ABC1ACED7330000E2F8 /* 05@2x.png */, 06758ABD1ACED7330000E2F8 /* 06@2x.png */, 06758ABE1ACED7330000E2F8 /* 07@2x.png */, 06758ABF1ACED7330000E2F8 /* 08@2x.png */, ); path = STDLoading; sourceTree = ""; }; 06C5185B1AAD4E3F00C2B2E3 /* PingTester */ = { isa = PBXGroup; children = ( 06C5185C1AAD4E3F00C2B2E3 /* SimplePing.h */, 06C5185D1AAD4E3F00C2B2E3 /* SimplePing.m */, ); path = PingTester; sourceTree = ""; }; 06C518621AAD4E6E00C2B2E3 /* Debug */ = { isa = PBXGroup; children = ( 060798EF1AC3E68A007C1AA7 /* STDAuthorization.h */, 060798F01AC3E68A007C1AA7 /* STDAuthorization.m */, 067A9F601AADA94B00651433 /* STDebugFoundation.h */, 067A9F611AADA94B00651433 /* STDebugFoundation.m */, 067A9F5D1AADA73300651433 /* STDDebugPingViewController.h */, 067A9F5E1AADA73300651433 /* STDDebugPingViewController.m */, 06C518631AAD4E6E00C2B2E3 /* STDLocationPickerController.h */, 06C518641AAD4E6E00C2B2E3 /* STDLocationPickerController.m */, 06C518661AAD519900C2B2E3 /* STDPingServices.h */, 06C518671AAD519900C2B2E3 /* STDPingServices.m */, ); path = Debug; sourceTree = ""; }; 06CB5FFE1A594F9900ABD7D3 /* Resources */ = { isa = PBXGroup; children = ( 06758AB71ACED7330000E2F8 /* STDLoading */, 066494F91A90AE930026D498 /* licenses.html */, 06CB5FFF1A594F9900ABD7D3 /* shangxin_292182.jpg */, 06CB60001A594F9900ABD7D3 /* shangxin_292182@2x.jpg */, ); path = Resources; sourceTree = ""; }; 06CB61E51A59523F00ABD7D3 /* Classes */ = { isa = PBXGroup; children = ( 0661EAEC1B8EE94700709CE6 /* STKit.framework */, 06CB61E61A59523F00ABD7D3 /* 3rdLibs */, 06CB636C1A59523F00ABD7D3 /* BaseUI */, 06CB63801A59523F00ABD7D3 /* Modules */, ); path = Classes; sourceTree = ""; }; 06CB61E61A59523F00ABD7D3 /* 3rdLibs */ = { isa = PBXGroup; children = ( 06C5185B1AAD4E3F00C2B2E3 /* PingTester */, 06CB63571A59523F00ABD7D3 /* MZCroppableView */, 06CB635C1A59523F00ABD7D3 /* SphereView */, ); path = 3rdLibs; sourceTree = ""; }; 06CB63571A59523F00ABD7D3 /* MZCroppableView */ = { isa = PBXGroup; children = ( 06CB63581A59523F00ABD7D3 /* MZCroppableView.h */, 06CB63591A59523F00ABD7D3 /* MZCroppableView.m */, 06CB635A1A59523F00ABD7D3 /* UIBezierPath-Points.h */, 06CB635B1A59523F00ABD7D3 /* UIBezierPath-Points.m */, ); path = MZCroppableView; sourceTree = ""; }; 06CB635C1A59523F00ABD7D3 /* SphereView */ = { isa = PBXGroup; children = ( 06CB635D1A59523F00ABD7D3 /* PFGoldenSectionSpiral.h */, 06CB635E1A59523F00ABD7D3 /* PFGoldenSectionSpiral.m */, 06CB635F1A59523F00ABD7D3 /* ZYQSphereView.h */, 06CB63601A59523F00ABD7D3 /* ZYQSphereView.m */, ); path = SphereView; sourceTree = ""; }; 06CB636C1A59523F00ABD7D3 /* BaseUI */ = { isa = PBXGroup; children = ( 06CB636D1A59523F00ABD7D3 /* SideBar */, 06CB63721A59523F00ABD7D3 /* STAlertView.h */, 06CB63731A59523F00ABD7D3 /* STAlertView.m */, 06CB63741A59523F00ABD7D3 /* STDropMenuView.h */, 06CB63751A59523F00ABD7D3 /* STDropMenuView.m */, 06CB63761A59523F00ABD7D3 /* STDTabBarController.h */, 06CB63771A59523F00ABD7D3 /* STDTabBarController.m */, 06CB63781A59523F00ABD7D3 /* STDTableViewController.h */, 06CB63791A59523F00ABD7D3 /* STDTableViewController.m */, 06CB637A1A59523F00ABD7D3 /* STDTextTableViewController.h */, 06CB637B1A59523F00ABD7D3 /* STDTextTableViewController.m */, 06CB637C1A59523F00ABD7D3 /* STDViewController.h */, 06CB637D1A59523F00ABD7D3 /* STDViewController.m */, 06CB637E1A59523F00ABD7D3 /* STMenuView.h */, 06CB637F1A59523F00ABD7D3 /* STMenuView.m */, 06479D501ACCF54200A44FB9 /* STDLoadingView.h */, 06479D511ACCF54200A44FB9 /* STDLoadingView.m */, 06479D531ACD101E00A44FB9 /* STDRefreshControl.h */, 06479D541ACD101E00A44FB9 /* STDRefreshControl.m */, 06758AC81ACEE09E0000E2F8 /* STDTransitionDelegate.h */, 06758AC91ACEE09E0000E2F8 /* STDTransitionDelegate.m */, 06758AD11ACEE38C0000E2F8 /* STDCardTransitionDelegate.h */, 06758AD21ACEE38C0000E2F8 /* STDCardTransitionDelegate.m */, 06758ACE1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.h */, 06758ACF1ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m */, 06758AD41AD3BC3F0000E2F8 /* STDScrollViewController.h */, 06758AD51AD3BC3F0000E2F8 /* STDScrollViewController.m */, 06DD3BF61B79CB6C002FA2B6 /* STDCoreDataManager.h */, 06DD3BF71B79CB6C002FA2B6 /* STDCoreDataManager.m */, ); path = BaseUI; sourceTree = ""; }; 06CB636D1A59523F00ABD7D3 /* SideBar */ = { isa = PBXGroup; children = ( 06CB636E1A59523F00ABD7D3 /* STDLeftViewController.h */, 06CB636F1A59523F00ABD7D3 /* STDLeftViewController.m */, 06CB63701A59523F00ABD7D3 /* STDSideBarController.h */, 06CB63711A59523F00ABD7D3 /* STDSideBarController.m */, ); path = SideBar; sourceTree = ""; }; 06CB63801A59523F00ABD7D3 /* Modules */ = { isa = PBXGroup; children = ( 065D78791A80C0AC0083D058 /* DesignPatterns */, 06CB63811A59523F00ABD7D3 /* Components */, 06CB64191A59523F00ABD7D3 /* Services */, 06CB64621A59523F00ABD7D3 /* Settings */, 06CB647A1A59523F00ABD7D3 /* STDSideBar */, 06CB647E1A59523F00ABD7D3 /* STDStartViewController.h */, 06CB647F1A59523F00ABD7D3 /* STDStartViewController.m */, ); path = Modules; sourceTree = ""; }; 06CB63811A59523F00ABD7D3 /* Components */ = { isa = PBXGroup; children = ( 06CB63FA1A59523F00ABD7D3 /* Image */, 06CB640C1A59523F00ABD7D3 /* STDemoViewController.h */, 06CB640D1A59523F00ABD7D3 /* STDemoViewController.m */, 06CB640E1A59523F00ABD7D3 /* STDImageBlurViewController.h */, 06CB640F1A59523F00ABD7D3 /* STDImageBlurViewController.m */, 06CB64101A59523F00ABD7D3 /* STDNavigationTestViewController.h */, 06CB64111A59523F00ABD7D3 /* STDNavigationTestViewController.m */, 06CB64121A59523F00ABD7D3 /* TextLayout */, 065D78B61A81ECB60083D058 /* STDScrollViewController.h */, 065D78B71A81ECB60083D058 /* STDScrollViewController.m */, ); path = Components; sourceTree = ""; }; 06CB63FA1A59523F00ABD7D3 /* Image */ = { isa = PBXGroup; children = ( 06CB64001A59523F00ABD7D3 /* STDCardViewController.h */, 06CB64011A59523F00ABD7D3 /* STDCardViewController.m */, 06CB64021A59523F00ABD7D3 /* STDFeedCell.h */, 06CB64031A59523F00ABD7D3 /* STDFeedCell.m */, 06CB64041A59523F00ABD7D3 /* STDFeedImageView.h */, 06CB64051A59523F00ABD7D3 /* STDFeedImageView.m */, 06CB64061A59523F00ABD7D3 /* STDFeedItem.h */, 06CB64071A59523F00ABD7D3 /* STDFeedItem.m */, 06CB64081A59523F00ABD7D3 /* STDFeedViewController.h */, 06CB64091A59523F00ABD7D3 /* STDFeedViewController.m */, 06CB640A1A59523F00ABD7D3 /* STDownloadViewController.h */, 06CB640B1A59523F00ABD7D3 /* STDownloadViewController.m */, ); path = Image; sourceTree = ""; }; 06CB64121A59523F00ABD7D3 /* TextLayout */ = { isa = PBXGroup; children = ( 06CB64131A59523F00ABD7D3 /* STDAboutViewController.h */, 06CB64141A59523F00ABD7D3 /* STDAboutViewController.m */, 06CB64151A59523F00ABD7D3 /* STDLinkViewController.h */, 06CB64161A59523F00ABD7D3 /* STDLinkViewController.m */, 06CB64171A59523F00ABD7D3 /* STDTextViewController.h */, 06CB64181A59523F00ABD7D3 /* STDTextViewController.m */, ); path = TextLayout; sourceTree = ""; }; 06CB64191A59523F00ABD7D3 /* Services */ = { isa = PBXGroup; children = ( 06CB641A1A59523F00ABD7D3 /* Algorithm */, 06CB642C1A59523F00ABD7D3 /* BookReader */, 06CB64341A59523F00ABD7D3 /* CoreData */, 06CB64571A59523F00ABD7D3 /* Recorder */, 06CB64601A59523F00ABD7D3 /* STDServiceViewController.h */, 06CB64611A59523F00ABD7D3 /* STDServiceViewController.m */, ); path = Services; sourceTree = ""; }; 06CB641A1A59523F00ABD7D3 /* Algorithm */ = { isa = PBXGroup; children = ( 06CB641B1A59523F00ABD7D3 /* STACodeViewController.h */, 06CB641C1A59523F00ABD7D3 /* STACodeViewController.m */, 06CB641D1A59523F00ABD7D3 /* STAHanoiOperation.h */, 06CB641E1A59523F00ABD7D3 /* STAHanoiOperation.m */, 06CB641F1A59523F00ABD7D3 /* STAHanoiView.h */, 06CB64201A59523F00ABD7D3 /* STAHanoiView.m */, 06CB64211A59523F00ABD7D3 /* STAHanoiViewController.h */, 06CB64221A59523F00ABD7D3 /* STAHanoiViewController.m */, 06CB64231A59523F00ABD7D3 /* STARootViewController.h */, 06CB64241A59523F00ABD7D3 /* STARootViewController.m */, 06CB64251A59523F00ABD7D3 /* STASortDefines.h */, 06CB64261A59523F00ABD7D3 /* STASortOperation.h */, 06CB64271A59523F00ABD7D3 /* STASortOperation.m */, 06CB64281A59523F00ABD7D3 /* STASortView.h */, 06CB64291A59523F00ABD7D3 /* STASortView.m */, 06CB642A1A59523F00ABD7D3 /* STASortViewController.h */, 06CB642B1A59523F00ABD7D3 /* STASortViewController.m */, ); path = Algorithm; sourceTree = ""; }; 06CB642C1A59523F00ABD7D3 /* BookReader */ = { isa = PBXGroup; children = ( 06CB642D1A59523F00ABD7D3 /* book.txt */, 06CB642E1A59523F00ABD7D3 /* STDBookViewController.h */, 06CB642F1A59523F00ABD7D3 /* STDBookViewController.m */, 06CB64301A59523F00ABD7D3 /* STDReaderViewController.h */, 06CB64311A59523F00ABD7D3 /* STDReaderViewController.m */, 06CB64321A59523F00ABD7D3 /* STRichView.h */, 06CB64331A59523F00ABD7D3 /* STRichView.m */, ); path = BookReader; sourceTree = ""; }; 06CB64341A59523F00ABD7D3 /* CoreData */ = { isa = PBXGroup; children = ( 06CF9BC51A8BC697000037EF /* STDModel.xcdatamodeld */, 06CB64351A59523F00ABD7D3 /* Entity */, 06CB64401A59523F00ABD7D3 /* STDBaseChatCell.h */, 06CB64411A59523F00ABD7D3 /* STDBaseChatCell.m */, 06CB64421A59523F00ABD7D3 /* STDChat.h */, 06CB64431A59523F00ABD7D3 /* STDChat.m */, 06CB64441A59523F00ABD7D3 /* STDChatInputView.h */, 06CB64451A59523F00ABD7D3 /* STDChatInputView.m */, 06CB64461A59523F00ABD7D3 /* STDChatViewController.h */, 06CB64471A59523F00ABD7D3 /* STDChatViewController.m */, 06CB64481A59523F00ABD7D3 /* STDImageChatCell.h */, 06CB64491A59523F00ABD7D3 /* STDImageChatCell.m */, 06CB644C1A59523F00ABD7D3 /* STDTextChatCell.h */, 06CB644D1A59523F00ABD7D3 /* STDTextChatCell.m */, 06CB644E1A59523F00ABD7D3 /* TestChat */, ); path = CoreData; sourceTree = ""; }; 06CB64351A59523F00ABD7D3 /* Entity */ = { isa = PBXGroup; children = ( 06CB64361A59523F00ABD7D3 /* STDEntityDefines.h */, 06CB64371A59523F00ABD7D3 /* STDImage.h */, 06CB64381A59523F00ABD7D3 /* STDImage.m */, 06CB64391A59523F00ABD7D3 /* STDMessage.h */, 06CB643A1A59523F00ABD7D3 /* STDMessage.m */, 06CB643B1A59523F00ABD7D3 /* STDSession.h */, 06CB643C1A59523F00ABD7D3 /* STDSession.m */, 06CB643D1A59523F00ABD7D3 /* STDUser.h */, 06CB643E1A59523F00ABD7D3 /* STDUser.m */, ); path = Entity; sourceTree = ""; }; 06CB644E1A59523F00ABD7D3 /* TestChat */ = { isa = PBXGroup; children = ( 06CB644F1A59523F00ABD7D3 /* chat_image_1.jpg */, 06CB64501A59523F00ABD7D3 /* chat_image_2.jpg */, 06CB64511A59523F00ABD7D3 /* chat_image_3.jpg */, 06CB64521A59523F00ABD7D3 /* chat_image_4.jpg */, 06CB64531A59523F00ABD7D3 /* chat_image_5.jpg */, 06CB64541A59523F00ABD7D3 /* chat_image_6.jpg */, 06CB64551A59523F00ABD7D3 /* chat_image_7.jpg */, 06CB64561A59523F00ABD7D3 /* chat_image_8.jpg */, ); path = TestChat; sourceTree = ""; }; 06CB64571A59523F00ABD7D3 /* Recorder */ = { isa = PBXGroup; children = ( 06CB64581A59523F00ABD7D3 /* SCSiriWaveformView.h */, 06CB64591A59523F00ABD7D3 /* SCSiriWaveformView.m */, 06CB645A1A59523F00ABD7D3 /* STDAboutAudioViewController.h */, 06CB645B1A59523F00ABD7D3 /* STDAboutAudioViewController.m */, 06CB645C1A59523F00ABD7D3 /* STDRecordViewController.h */, 06CB645D1A59523F00ABD7D3 /* STDRecordViewController.m */, 06CB645E1A59523F00ABD7D3 /* STWaveBarView.h */, 06CB645F1A59523F00ABD7D3 /* STWaveBarView.m */, ); path = Recorder; sourceTree = ""; }; 06CB64621A59523F00ABD7D3 /* Settings */ = { isa = PBXGroup; children = ( 06C518621AAD4E6E00C2B2E3 /* Debug */, 06CB64751A59523F00ABD7D3 /* STDMoreViewController.h */, 06CB64761A59523F00ABD7D3 /* STDMoreViewController.m */, 0664952D1A90C6020026D498 /* STDSettingViewController.h */, 0664952E1A90C6020026D498 /* STDSettingViewController.m */, 06CB64771A59523F00ABD7D3 /* STDNavigationSettingViewController.h */, 06CB64781A59523F00ABD7D3 /* STDNavigationSettingViewController.m */, 06CB64791A59523F00ABD7D3 /* STDNavigationSettingViewController.xib */, ); path = Settings; sourceTree = ""; }; 06CB647A1A59523F00ABD7D3 /* STDSideBar */ = { isa = PBXGroup; children = ( 06CB647B1A59523F00ABD7D3 /* STDMapViewController.h */, 06CB647C1A59523F00ABD7D3 /* STDMapViewController.m */, 06CB647D1A59523F00ABD7D3 /* STDMapViewController.xib */, ); path = STDSideBar; sourceTree = ""; }; 06CF9BC91A8BD2A3000037EF /* STKitDemoTests */ = { isa = PBXGroup; children = ( 06CF9BCA1A8BD2A3000037EF /* DesignPatterns */, 06CF9BD01A8BD2A3000037EF /* Info.plist */, 06CF9BD11A8BD2A3000037EF /* STKitDemoTests.m */, ); path = STKitDemoTests; sourceTree = ""; }; 06CF9BCA1A8BD2A3000037EF /* DesignPatterns */ = { isa = PBXGroup; children = ( 06CF9BCB1A8BD2A3000037EF /* Creational */, 06CF9BCF1A8BD2A3000037EF /* Structural */, ); path = DesignPatterns; sourceTree = ""; }; 06CF9BCB1A8BD2A3000037EF /* Creational */ = { isa = PBXGroup; children = ( 06CF9BCC1A8BD2A3000037EF /* STDAbstractFactoryTests.m */, 06CF9BCD1A8BD2A3000037EF /* STDFactoryMethodTests.m */, 06CF9BCE1A8BD2A3000037EF /* STDSingletonTests.m */, ); path = Creational; sourceTree = ""; }; 06CF9BCF1A8BD2A3000037EF /* Structural */ = { isa = PBXGroup; children = ( ); path = Structural; sourceTree = ""; }; F6471E6D1851CD7C00574E94 = { isa = PBXGroup; children = ( F6471E7F1851CD7C00574E94 /* STKitDemo */, 06CF9BC91A8BD2A3000037EF /* STKitDemoTests */, F6471E781851CD7C00574E94 /* Frameworks */, F6471E771851CD7C00574E94 /* Products */, ); sourceTree = ""; }; F6471E771851CD7C00574E94 /* Products */ = { isa = PBXGroup; children = ( 0602B51B196974150004ACBB /* STKitDemo.app */, 06CF9BAC1A8BB802000037EF /* STKitDemoTests.xctest */, 0642E2BD1AE0F3D100B820D1 /* STKitDemo.app */, ); name = Products; sourceTree = ""; }; F6471E781851CD7C00574E94 /* Frameworks */ = { isa = PBXGroup; children = ( 06E0FEDA1C328B2500D1022A /* MobileCoreServices.framework */, 06E0FED81C328B0300D1022A /* CoreImage.framework */, 06E0FED31C3288A500D1022A /* Accelerate.framework */, 06E0FED11C32889700D1022A /* ImageIO.framework */, 065D78E41A8382AC0083D058 /* CFNetwork.framework */, 06CFCB9C1A63973C003DDC93 /* SpriteKit.framework */, 06DBF9E019F8CFBB009ECABA /* Social.framework */, 0681CCDA19D3BC9A00D897AF /* Photos.framework */, 0698C21C19D1CCE400D0D69A /* WebKit.framework */, 06A1CD371978DE3500F68F35 /* libstdc++.6.dylib */, 06A1CD351978DE1400F68F35 /* libstdc++.dylib */, 06A1CD331978DE0700F68F35 /* CoreTelephony.framework */, 06C6F9CD1920F0C10028B2B3 /* CoreLocation.framework */, 06291AE4191F314700EDBD35 /* libxml2.dylib */, F69CFE261873032B00327D8A /* libz.dylib */, F6E5B875186413A700FF3408 /* AVFoundation.framework */, F6E5B8721864139D00FF3408 /* AudioToolbox.framework */, F66A09E318522F2A002D0597 /* SystemConfiguration.framework */, F6471EE31851CED400574E94 /* QuartzCore.framework */, F6471EE11851CECF00574E94 /* MapKit.framework */, F6471E791851CD7C00574E94 /* Foundation.framework */, F6471E7B1851CD7C00574E94 /* CoreGraphics.framework */, F6471E7D1851CD7C00574E94 /* UIKit.framework */, 06A4D3BF19E6B3C7007D332D /* NotificationCenter.framework */, ); name = Frameworks; sourceTree = ""; }; F6471E7F1851CD7C00574E94 /* STKitDemo */ = { isa = PBXGroup; children = ( 06CB61E51A59523F00ABD7D3 /* Classes */, 06CB5FFE1A594F9900ABD7D3 /* Resources */, F6471E881851CD7C00574E94 /* STDAppDelegate.h */, F6471E891851CD7C00574E94 /* STDAppDelegate.m */, 06BE56D01A0404CF00FBC4C8 /* STDemoImages.xcassets */, 06A4D46719E80498007D332D /* STKitDemo.entitlements */, 0634101A19C9EBE3003BC34E /* LaunchScreen.xib */, F6471E801851CD7C00574E94 /* Supporting Files */, ); path = STKitDemo; sourceTree = ""; }; F6471E801851CD7C00574E94 /* Supporting Files */ = { isa = PBXGroup; children = ( 0642E2BF1AE0F45D00B820D1 /* STKitDemoInHouse-Info.plist */, F6471E811851CD7C00574E94 /* STKitDemo-Info.plist */, F6471E821851CD7C00574E94 /* InfoPlist.strings */, F6471E851851CD7C00574E94 /* main.m */, F6471E871851CD7C00574E94 /* STKitDemo-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 0602B48E196974150004ACBB /* STKitDemo */ = { isa = PBXNativeTarget; buildConfigurationList = 0602B518196974150004ACBB /* Build configuration list for PBXNativeTarget "STKitDemo" */; buildPhases = ( 0602B48F196974150004ACBB /* Sources */, 0602B4F5196974150004ACBB /* Frameworks */, 0602B504196974150004ACBB /* Resources */, 069586EA1AE5FF6100F149F1 /* Embed App Extensions */, ); buildRules = ( ); dependencies = ( ); name = STKitDemo; productName = STKitDemo; productReference = 0602B51B196974150004ACBB /* STKitDemo.app */; productType = "com.apple.product-type.application"; }; 0642E2301AE0F3D100B820D1 /* STKitDemoInHouse */ = { isa = PBXNativeTarget; buildConfigurationList = 0642E2BA1AE0F3D100B820D1 /* Build configuration list for PBXNativeTarget "STKitDemoInHouse" */; buildPhases = ( 0642E2331AE0F3D100B820D1 /* Sources */, 0642E2891AE0F3D100B820D1 /* Frameworks */, 0642E29B1AE0F3D100B820D1 /* Resources */, 0642E2D71AE0F51A00B820D1 /* Embed App Extensions */, ); buildRules = ( ); dependencies = ( ); name = STKitDemoInHouse; productName = STKitDemo; productReference = 0642E2BD1AE0F3D100B820D1 /* STKitDemo.app */; productType = "com.apple.product-type.application"; }; 06CF9BAB1A8BB802000037EF /* STKitDemoTests */ = { isa = PBXNativeTarget; buildConfigurationList = 06CF9BB41A8BB802000037EF /* Build configuration list for PBXNativeTarget "STKitDemoTests" */; buildPhases = ( 06CF9BA81A8BB802000037EF /* Sources */, 06CF9BA91A8BB802000037EF /* Frameworks */, 06CF9BAA1A8BB802000037EF /* Resources */, ); buildRules = ( ); dependencies = ( 06CF9BB31A8BB802000037EF /* PBXTargetDependency */, ); name = STKitDemoTests; productName = STKitDemoTests; productReference = 06CF9BAC1A8BB802000037EF /* STKitDemoTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ F6471E6E1851CD7C00574E94 /* Project object */ = { isa = PBXProject; attributes = { CLASSPREFIX = STD; LastUpgradeCheck = 0720; ORGANIZATIONNAME = SunJiangting; TargetAttributes = { 0602B48E196974150004ACBB = { SystemCapabilities = { com.apple.ApplicationGroups.iOS = { enabled = 0; }; com.apple.BackgroundModes = { enabled = 0; }; }; }; 0642E2301AE0F3D100B820D1 = { DevelopmentTeam = XXHND5J98K; }; 06CF9BAB1A8BB802000037EF = { CreatedOnToolsVersion = 6.1; TestTargetID = 0602B48E196974150004ACBB; }; }; }; buildConfigurationList = F6471E711851CD7C00574E94 /* Build configuration list for PBXProject "STKitDemo" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = F6471E6D1851CD7C00574E94; productRefGroup = F6471E771851CD7C00574E94 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 0602B48E196974150004ACBB /* STKitDemo */, 0642E2301AE0F3D100B820D1 /* STKitDemoInHouse */, 06CF9BAB1A8BB802000037EF /* STKitDemoTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 0602B504196974150004ACBB /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 06CB60011A594F9900ABD7D3 /* shangxin_292182.jpg in Resources */, 06758AC11ACED7330000E2F8 /* 02@2x.png in Resources */, 06758AC51ACED7330000E2F8 /* 06@2x.png in Resources */, 06CB60021A594F9900ABD7D3 /* shangxin_292182@2x.jpg in Resources */, 06CB65D01A59524000ABD7D3 /* chat_image_5.jpg in Resources */, 062BAE041B8971C8004380A2 /* STDemoImages.xcassets in Resources */, 066494FA1A90AE930026D498 /* licenses.html in Resources */, 06CB65D11A59524000ABD7D3 /* chat_image_6.jpg in Resources */, 06CB65CC1A59524000ABD7D3 /* chat_image_1.jpg in Resources */, 0602B512196974150004ACBB /* InfoPlist.strings in Resources */, 06CB65D31A59524000ABD7D3 /* chat_image_8.jpg in Resources */, 06CB65CE1A59524000ABD7D3 /* chat_image_3.jpg in Resources */, 06CB65E61A59524000ABD7D3 /* STDMapViewController.xib in Resources */, 06CB65BC1A59523F00ABD7D3 /* book.txt in Resources */, 06758AC01ACED7330000E2F8 /* 01@2x.png in Resources */, 06CB65CD1A59524000ABD7D3 /* chat_image_2.jpg in Resources */, 06758AC31ACED7330000E2F8 /* 04@2x.png in Resources */, 06CB65CF1A59524000ABD7D3 /* chat_image_4.jpg in Resources */, 06758AC41ACED7330000E2F8 /* 05@2x.png in Resources */, 06758AC71ACED7330000E2F8 /* 08@2x.png in Resources */, 06758AC21ACED7330000E2F8 /* 03@2x.png in Resources */, 062BAE061B897202004380A2 /* LaunchScreen.xib in Resources */, 06CB65D21A59524000ABD7D3 /* chat_image_7.jpg in Resources */, 06758AC61ACED7330000E2F8 /* 07@2x.png in Resources */, 06CB65E41A59524000ABD7D3 /* STDNavigationSettingViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0642E29B1AE0F3D100B820D1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 0642E29D1AE0F3D100B820D1 /* shangxin_292182.jpg in Resources */, 0642E29E1AE0F3D100B820D1 /* 02@2x.png in Resources */, 0642E2A01AE0F3D100B820D1 /* 06@2x.png in Resources */, 0642E2A11AE0F3D100B820D1 /* shangxin_292182@2x.jpg in Resources */, 0642E2A31AE0F3D100B820D1 /* chat_image_5.jpg in Resources */, 062BAE031B8971C6004380A2 /* STDemoImages.xcassets in Resources */, 0642E2A41AE0F3D100B820D1 /* licenses.html in Resources */, 0642E2A51AE0F3D100B820D1 /* chat_image_6.jpg in Resources */, 0642E2A61AE0F3D100B820D1 /* chat_image_1.jpg in Resources */, 0642E2A71AE0F3D100B820D1 /* InfoPlist.strings in Resources */, 0642E2A81AE0F3D100B820D1 /* chat_image_8.jpg in Resources */, 0642E2AA1AE0F3D100B820D1 /* chat_image_3.jpg in Resources */, 0642E2AB1AE0F3D100B820D1 /* STDMapViewController.xib in Resources */, 0642E2AC1AE0F3D100B820D1 /* book.txt in Resources */, 0642E2AD1AE0F3D100B820D1 /* 01@2x.png in Resources */, 0642E2AE1AE0F3D100B820D1 /* chat_image_2.jpg in Resources */, 0642E2AF1AE0F3D100B820D1 /* 04@2x.png in Resources */, 0642E2B01AE0F3D100B820D1 /* chat_image_4.jpg in Resources */, 0642E2B11AE0F3D100B820D1 /* 05@2x.png in Resources */, 0642E2B21AE0F3D100B820D1 /* 08@2x.png in Resources */, 0642E2B31AE0F3D100B820D1 /* 03@2x.png in Resources */, 062BAE051B897201004380A2 /* LaunchScreen.xib in Resources */, 0642E2B41AE0F3D100B820D1 /* chat_image_7.jpg in Resources */, 0642E2B51AE0F3D100B820D1 /* 07@2x.png in Resources */, 0642E2B71AE0F3D100B820D1 /* STDNavigationSettingViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; 06CF9BAA1A8BB802000037EF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 0602B48F196974150004ACBB /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 06CB65371A59523F00ABD7D3 /* STDLeftViewController.m in Sources */, 06CB65E21A59524000ABD7D3 /* STDMoreViewController.m in Sources */, 06CB65C21A59523F00ABD7D3 /* STDSession.m in Sources */, 06CB653D1A59523F00ABD7D3 /* STDTextTableViewController.m in Sources */, 06C518651AAD4E6E00C2B2E3 /* STDLocationPickerController.m in Sources */, 06479D521ACCF54200A44FB9 /* STDLoadingView.m in Sources */, 0602B499196974150004ACBB /* STDAppDelegate.m in Sources */, 06CB653A1A59523F00ABD7D3 /* STDropMenuView.m in Sources */, 06CB65D71A59524000ABD7D3 /* STWaveBarView.m in Sources */, 06CB65BB1A59523F00ABD7D3 /* STASortViewController.m in Sources */, 06CB65D61A59524000ABD7D3 /* STDRecordViewController.m in Sources */, 06CB65C51A59523F00ABD7D3 /* STDBaseChatCell.m in Sources */, 06CB65301A59523F00ABD7D3 /* UIBezierPath-Points.m in Sources */, 06CB65C01A59523F00ABD7D3 /* STDImage.m in Sources */, 065D78D21A822ECF0083D058 /* STDAbstractFactory.m in Sources */, 06CB65391A59523F00ABD7D3 /* STAlertView.m in Sources */, 06CB65B61A59523F00ABD7D3 /* STAHanoiView.m in Sources */, 065D78DB1A8230640083D058 /* STDAdapter.m in Sources */, 06CB65D81A59524000ABD7D3 /* STDServiceViewController.m in Sources */, 065B7C911B3FF573006EFEDA /* STDFeedItem.m in Sources */, 06758AD31ACEE38C0000E2F8 /* STDCardTransitionDelegate.m in Sources */, 06758ACA1ACEE09E0000E2F8 /* STDTransitionDelegate.m in Sources */, 06CF9BC71A8BC697000037EF /* STDModel.xcdatamodeld in Sources */, 06CB65B21A59523F00ABD7D3 /* STDLinkViewController.m in Sources */, 06CB65D41A59524000ABD7D3 /* SCSiriWaveformView.m in Sources */, 065D78E11A834AF00083D058 /* STDProxy.m in Sources */, 0602B49D196974150004ACBB /* main.m in Sources */, 06CB65381A59523F00ABD7D3 /* STDSideBarController.m in Sources */, 06CB65BE1A59523F00ABD7D3 /* STDReaderViewController.m in Sources */, 06CB65B81A59523F00ABD7D3 /* STARootViewController.m in Sources */, 06CB65B01A59523F00ABD7D3 /* STDNavigationTestViewController.m in Sources */, 06CB65B11A59523F00ABD7D3 /* STDAboutViewController.m in Sources */, 06CB65E71A59524000ABD7D3 /* STDStartViewController.m in Sources */, 065D78D51A822ECF0083D058 /* STDPrototype.m in Sources */, 06CB65C61A59523F00ABD7D3 /* STDChat.m in Sources */, 06CB652F1A59523F00ABD7D3 /* MZCroppableView.m in Sources */, 06CB65BD1A59523F00ABD7D3 /* STDBookViewController.m in Sources */, 06CB65C11A59523F00ABD7D3 /* STDMessage.m in Sources */, 06CB65C91A59523F00ABD7D3 /* STDImageChatCell.m in Sources */, 06CB65321A59523F00ABD7D3 /* ZYQSphereView.m in Sources */, 06CB65C71A59523F00ABD7D3 /* STDChatInputView.m in Sources */, 06CB65AE1A59523F00ABD7D3 /* STDemoViewController.m in Sources */, 06CB65E51A59524000ABD7D3 /* STDMapViewController.m in Sources */, 06CB65BF1A59523F00ABD7D3 /* STRichView.m in Sources */, 06C518601AAD4E3F00C2B2E3 /* SimplePing.m in Sources */, 06CB653E1A59523F00ABD7D3 /* STDViewController.m in Sources */, 06CB65AF1A59523F00ABD7D3 /* STDImageBlurViewController.m in Sources */, 06CB65B91A59523F00ABD7D3 /* STASortOperation.m in Sources */, 06C518681AAD519900C2B2E3 /* STDPingServices.m in Sources */, 06CB653C1A59523F00ABD7D3 /* STDTableViewController.m in Sources */, 06CB65311A59523F00ABD7D3 /* PFGoldenSectionSpiral.m in Sources */, 06CB653B1A59523F00ABD7D3 /* STDTabBarController.m in Sources */, 067A9F621AADA94B00651433 /* STDebugFoundation.m in Sources */, 065D78D31A822ECF0083D058 /* STDBuilder.m in Sources */, 06CB65AD1A59523F00ABD7D3 /* STDownloadViewController.m in Sources */, 06CB65B41A59523F00ABD7D3 /* STACodeViewController.m in Sources */, 06CB65A81A59523F00ABD7D3 /* STDCardViewController.m in Sources */, 06CB65D51A59524000ABD7D3 /* STDAboutAudioViewController.m in Sources */, 06CB65C81A59523F00ABD7D3 /* STDChatViewController.m in Sources */, 065D78D61A822ECF0083D058 /* STDSingleton.m in Sources */, 06CB65AC1A59523F00ABD7D3 /* STDFeedViewController.m in Sources */, 06CB65B71A59523F00ABD7D3 /* STAHanoiViewController.m in Sources */, 067A9F5F1AADA73300651433 /* STDDebugPingViewController.m in Sources */, 06DD3BF81B79CB6C002FA2B6 /* STDCoreDataManager.m in Sources */, 065D78DE1A8344C30083D058 /* STDFacade.m in Sources */, 06CB65C31A59523F00ABD7D3 /* STDUser.m in Sources */, 06758AD61AD3BC3F0000E2F8 /* STDScrollViewController.m in Sources */, 06CB65B31A59523F00ABD7D3 /* STDTextViewController.m in Sources */, 06CB88A61A88C8C40082DACA /* STDBridge.m in Sources */, 060798F11AC3E68A007C1AA7 /* STDAuthorization.m in Sources */, 0664952F1A90C6020026D498 /* STDSettingViewController.m in Sources */, 06758AD01ACEE34D0000E2F8 /* STDRotateTransitionDelegate.m in Sources */, 065D78D41A822ECF0083D058 /* STDFactoryMethod.m in Sources */, 06CB65BA1A59523F00ABD7D3 /* STASortView.m in Sources */, 06CB65E31A59524000ABD7D3 /* STDNavigationSettingViewController.m in Sources */, 06CB65A91A59523F00ABD7D3 /* STDFeedCell.m in Sources */, 06CB653F1A59523F00ABD7D3 /* STMenuView.m in Sources */, 06CB65CB1A59524000ABD7D3 /* STDTextChatCell.m in Sources */, 06CB65AA1A59523F00ABD7D3 /* STDFeedImageView.m in Sources */, 06CB65B51A59523F00ABD7D3 /* STAHanoiOperation.m in Sources */, 06479D551ACD101E00A44FB9 /* STDRefreshControl.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 0642E2331AE0F3D100B820D1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 0642E2341AE0F3D100B820D1 /* STDLeftViewController.m in Sources */, 0642E2361AE0F3D100B820D1 /* STDMoreViewController.m in Sources */, 0642E2371AE0F3D100B820D1 /* STDSession.m in Sources */, 0642E2381AE0F3D100B820D1 /* STDTextTableViewController.m in Sources */, 0642E2391AE0F3D100B820D1 /* STDLocationPickerController.m in Sources */, 0642E23A1AE0F3D100B820D1 /* STDLoadingView.m in Sources */, 0642E23B1AE0F3D100B820D1 /* STDAppDelegate.m in Sources */, 0642E23C1AE0F3D100B820D1 /* STDropMenuView.m in Sources */, 0642E23D1AE0F3D100B820D1 /* STWaveBarView.m in Sources */, 0642E23F1AE0F3D100B820D1 /* STASortViewController.m in Sources */, 0642E2401AE0F3D100B820D1 /* STDRecordViewController.m in Sources */, 0642E2411AE0F3D100B820D1 /* STDBaseChatCell.m in Sources */, 0642E2421AE0F3D100B820D1 /* UIBezierPath-Points.m in Sources */, 0642E2431AE0F3D100B820D1 /* STDImage.m in Sources */, 0642E2441AE0F3D100B820D1 /* STDAbstractFactory.m in Sources */, 0642E2451AE0F3D100B820D1 /* STAlertView.m in Sources */, 0642E2461AE0F3D100B820D1 /* STAHanoiView.m in Sources */, 0642E2471AE0F3D100B820D1 /* STDAdapter.m in Sources */, 0642E2481AE0F3D100B820D1 /* STDServiceViewController.m in Sources */, 0642E2491AE0F3D100B820D1 /* STDCardTransitionDelegate.m in Sources */, 0642E24A1AE0F3D100B820D1 /* STDTransitionDelegate.m in Sources */, 0642E24B1AE0F3D100B820D1 /* STDModel.xcdatamodeld in Sources */, 0642E24C1AE0F3D100B820D1 /* STDLinkViewController.m in Sources */, 0642E24D1AE0F3D100B820D1 /* SCSiriWaveformView.m in Sources */, 0642E24F1AE0F3D100B820D1 /* STDProxy.m in Sources */, 0642E2501AE0F3D100B820D1 /* main.m in Sources */, 0642E2511AE0F3D100B820D1 /* STDSideBarController.m in Sources */, 0642E2521AE0F3D100B820D1 /* STDReaderViewController.m in Sources */, 0642E2531AE0F3D100B820D1 /* STARootViewController.m in Sources */, 0642E2541AE0F3D100B820D1 /* STDNavigationTestViewController.m in Sources */, 0642E2551AE0F3D100B820D1 /* STDAboutViewController.m in Sources */, 0642E2561AE0F3D100B820D1 /* STDStartViewController.m in Sources */, 0642E2571AE0F3D100B820D1 /* STDPrototype.m in Sources */, 0642E2581AE0F3D100B820D1 /* STDChat.m in Sources */, 0642E2591AE0F3D100B820D1 /* MZCroppableView.m in Sources */, 0642E25A1AE0F3D100B820D1 /* STDBookViewController.m in Sources */, 0642E25B1AE0F3D100B820D1 /* STDMessage.m in Sources */, 0642E25C1AE0F3D100B820D1 /* STDImageChatCell.m in Sources */, 0642E25D1AE0F3D100B820D1 /* ZYQSphereView.m in Sources */, 0642E25E1AE0F3D100B820D1 /* STDChatInputView.m in Sources */, 0642E25F1AE0F3D100B820D1 /* STDemoViewController.m in Sources */, 0642E2601AE0F3D100B820D1 /* STDMapViewController.m in Sources */, 0642E2611AE0F3D100B820D1 /* STRichView.m in Sources */, 0642E2621AE0F3D100B820D1 /* SimplePing.m in Sources */, 0642E2631AE0F3D100B820D1 /* STDViewController.m in Sources */, 0642E2641AE0F3D100B820D1 /* STDImageBlurViewController.m in Sources */, 0642E2651AE0F3D100B820D1 /* STASortOperation.m in Sources */, 0642E2661AE0F3D100B820D1 /* STDPingServices.m in Sources */, 0642E2671AE0F3D100B820D1 /* STDTableViewController.m in Sources */, 0642E2681AE0F3D100B820D1 /* PFGoldenSectionSpiral.m in Sources */, 0642E2691AE0F3D100B820D1 /* STDTabBarController.m in Sources */, 0642E26A1AE0F3D100B820D1 /* STDebugFoundation.m in Sources */, 0642E26B1AE0F3D100B820D1 /* STDBuilder.m in Sources */, 0642E26E1AE0F3D100B820D1 /* STDownloadViewController.m in Sources */, 0642E26F1AE0F3D100B820D1 /* STACodeViewController.m in Sources */, 0642E2701AE0F3D100B820D1 /* STDCardViewController.m in Sources */, 0642E2711AE0F3D100B820D1 /* STDAboutAudioViewController.m in Sources */, 0642E2721AE0F3D100B820D1 /* STDChatViewController.m in Sources */, 0642E2731AE0F3D100B820D1 /* STDSingleton.m in Sources */, 0642E2741AE0F3D100B820D1 /* STDFeedViewController.m in Sources */, 0642E2751AE0F3D100B820D1 /* STAHanoiViewController.m in Sources */, 0642E2761AE0F3D100B820D1 /* STDDebugPingViewController.m in Sources */, 0642E2771AE0F3D100B820D1 /* STDFacade.m in Sources */, 06DD3BF91B79CB6C002FA2B6 /* STDCoreDataManager.m in Sources */, 0642E2781AE0F3D100B820D1 /* STDUser.m in Sources */, 0642E2791AE0F3D100B820D1 /* STDScrollViewController.m in Sources */, 0642E27A1AE0F3D100B820D1 /* STDTextViewController.m in Sources */, 0642E27B1AE0F3D100B820D1 /* STDBridge.m in Sources */, 0642E27C1AE0F3D100B820D1 /* STDAuthorization.m in Sources */, 0642E27D1AE0F3D100B820D1 /* STDSettingViewController.m in Sources */, 0642E27E1AE0F3D100B820D1 /* STDRotateTransitionDelegate.m in Sources */, 0642E27F1AE0F3D100B820D1 /* STDFeedItem.m in Sources */, 0642E2801AE0F3D100B820D1 /* STDFactoryMethod.m in Sources */, 0642E2811AE0F3D100B820D1 /* STASortView.m in Sources */, 0642E2821AE0F3D100B820D1 /* STDNavigationSettingViewController.m in Sources */, 0642E2831AE0F3D100B820D1 /* STDFeedCell.m in Sources */, 0642E2841AE0F3D100B820D1 /* STMenuView.m in Sources */, 0642E2851AE0F3D100B820D1 /* STDTextChatCell.m in Sources */, 0642E2861AE0F3D100B820D1 /* STDFeedImageView.m in Sources */, 0642E2871AE0F3D100B820D1 /* STAHanoiOperation.m in Sources */, 0642E2881AE0F3D100B820D1 /* STDRefreshControl.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; 06CF9BA81A8BB802000037EF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 06CF9BD21A8BD2A3000037EF /* STDAbstractFactoryTests.m in Sources */, 06CF9BD31A8BD2A3000037EF /* STDFactoryMethodTests.m in Sources */, 06CF9BD61A8BD2A3000037EF /* STKitDemoTests.m in Sources */, 06CF9BD41A8BD2A3000037EF /* STDSingletonTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ 06CF9BB31A8BB802000037EF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 0602B48E196974150004ACBB /* STKitDemo */; targetProxy = 06CF9BB21A8BB802000037EF /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ F6471E821851CD7C00574E94 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( F6471E831851CD7C00574E94 /* en */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 0602B519196974150004ACBB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "STKitDemo/STKitDemo-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, ); INFOPLIST_FILE = "$(SRCROOT)/STKitDemo/STKitDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", ); ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = STKitDemo; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 arm64"; WRAPPER_EXTENSION = app; }; name = Debug; }; 0602B51A196974150004ACBB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: WEIWEI YE (U9JEY66N6A)"; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "STKitDemo/STKitDemo-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, ); INFOPLIST_FILE = "$(SRCROOT)/STKitDemo/STKitDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 7.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", ); ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = STKitDemo; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 arm64"; WRAPPER_EXTENSION = app; }; name = Release; }; 0642E2BB1AE0F3D100B820D1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "STKitDemo/STKitDemo-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, ); INFOPLIST_FILE = "STKitDemo/STKitDemoInHouse-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", ); ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.app.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = STKitDemo; PROVISIONING_PROFILE = "c91df21d-8649-45cd-9714-e2d34515ffc7"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 arm64"; WRAPPER_EXTENSION = app; }; name = Debug; }; 0642E2BC1AE0F3D100B820D1 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=*]" = "iPhone Distribution: Beijing Bytedance Technology Co., Ltd"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Beijing Bytedance Technology Co., Ltd"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "STKitDemo/STKitDemo-Prefix.pch"; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, ); INFOPLIST_FILE = "STKitDemo/STKitDemoInHouse-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/STKitDemo", "$(PROJECT_DIR)/STKitDemo/Classes/3rdLibs", ); ONLY_ACTIVE_ARCH = NO; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.app.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = STKitDemo; PROVISIONING_PROFILE = "c91df21d-8649-45cd-9714-e2d34515ffc7"; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "armv7 arm64"; WRAPPER_EXTENSION = app; }; name = Release; }; 06CF9BB51A8BB802000037EF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_WARN_UNREACHABLE_CODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(PROJECT_DIR)/STKitDemo/Classes", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = STKitDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/STKitDemo.app/STKitDemo"; }; name = Debug; }; 06CF9BB61A8BB802000037EF /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_WARN_UNREACHABLE_CODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(PROJECT_DIR)/STKitDemo/Classes", "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/STWorkspace-geijllfmuymgingxsjgqvtuhlffp/Build/Products/Debug-iphonesimulator", ); GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = STKitDemoTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.suen.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/STKitDemo.app/STKitDemo"; }; name = Release; }; F6471EA61851CD7C00574E94 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 7.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; VALID_ARCHS = "armv7 arm64"; }; name = Debug; }; F6471EA71851CD7C00574E94 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 7.0; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; VALID_ARCHS = "armv7 arm64"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 0602B518196974150004ACBB /* Build configuration list for PBXNativeTarget "STKitDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( 0602B519196974150004ACBB /* Debug */, 0602B51A196974150004ACBB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 0642E2BA1AE0F3D100B820D1 /* Build configuration list for PBXNativeTarget "STKitDemoInHouse" */ = { isa = XCConfigurationList; buildConfigurations = ( 0642E2BB1AE0F3D100B820D1 /* Debug */, 0642E2BC1AE0F3D100B820D1 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 06CF9BB41A8BB802000037EF /* Build configuration list for PBXNativeTarget "STKitDemoTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 06CF9BB51A8BB802000037EF /* Debug */, 06CF9BB61A8BB802000037EF /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; F6471E711851CD7C00574E94 /* Build configuration list for PBXProject "STKitDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( F6471EA61851CD7C00574E94 /* Debug */, F6471EA71851CD7C00574E94 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ /* Begin XCVersionGroup section */ 06CF9BC51A8BC697000037EF /* STDModel.xcdatamodeld */ = { isa = XCVersionGroup; children = ( 06CF9BC81A8BC6B0000037EF /* STDModel 2.xcdatamodel */, 06CF9BC61A8BC697000037EF /* STDModel.xcdatamodel */, ); currentVersion = 06CF9BC81A8BC6B0000037EF /* STDModel 2.xcdatamodel */; path = STDModel.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; }; /* End XCVersionGroup section */ }; rootObject = F6471E6E1851CD7C00574E94 /* Project object */; } ================================================ FILE: STKitDemoTests/DesignPatterns/Creational/STDAbstractFactoryTests.m ================================================ // // STDAbstractFactoryTests.m // STKitDemo // // Created by SunJiangting on 15-2-12. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDAbstractFactory.h" @interface STDAbstractFactoryTests : XCTestCase @end @implementation STDAbstractFactoryTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testCreateProductA { id productA = [STDFactoryA createProduct]; [productA printProductName]; XCTAssertTrue([productA isKindOfClass:[STDProductA class]]); } - (void)testCreateProductB { id productB = [STDFactoryB createProduct]; [productB printProductName]; XCTAssertTrue([productB isKindOfClass:[STDProductB class]]); } @end ================================================ FILE: STKitDemoTests/DesignPatterns/Creational/STDFactoryMethodTests.m ================================================ // // STDFactoryMethodTests.m // STKitDemo // // Created by SunJiangting on 15-2-11. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDFactoryMethod.h" @interface STDFactoryMethodTests : XCTestCase @end @implementation STDFactoryMethodTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testCreateProduct { id product = [STDFactoryMethod createProduct]; [product printProductName]; XCTAssertTrue([product isKindOfClass:[STDFactoryMethodProduct class]]); } @end ================================================ FILE: STKitDemoTests/DesignPatterns/Creational/STDSingletonTests.m ================================================ // // STDSingletonTests.m // STKitDemo // // Created by SunJiangting on 15-2-12. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import "STDSingleton.h" @interface STDSingletonTests : XCTestCase { NSString *_globalName; NSString *_memoryAddress; } @end @implementation STDSingletonTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. _globalName = @"Test"; [STDSingleton sharedInstance].globalName = _globalName; _memoryAddress = [NSString stringWithFormat:@"%p", [STDSingleton sharedInstance]]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. _globalName = nil; _memoryAddress = nil; [super tearDown]; } - (void)testSingletonProperty { // This is an example of a functional test case. XCTAssert([[STDSingleton sharedInstance].globalName isEqualToString:_globalName], @"Pass"); } - (void)testSingletonMemoryAddress { NSString *currentAddress = [NSString stringWithFormat:@"%p", [STDSingleton sharedInstance]]; XCTAssert([currentAddress isEqualToString:_memoryAddress], @"Pass"); } @end ================================================ FILE: STKitDemoTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: STKitDemoTests/STKitDemoTests.m ================================================ // // STKitDemoTests.m // STKitDemoTests // // Created by SunJiangting on 15-2-12. // Copyright (c) 2015年 SunJiangting. All rights reserved. // #import #import @interface STKitDemoTests : XCTestCase @end @implementation STKitDemoTests - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testExample { // This is an example of a functional test case. XCTAssert(YES, @"Pass"); } - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ // Put the code you want to measure the time of here. }]; } @end ================================================ FILE: STKitWidget/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName STKitWidget CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier com.suen.STKitDemo.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType XPC! CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 NSExtension NSExtensionMainStoryboard MainInterface NSExtensionPointIdentifier com.apple.widget-extension ================================================ FILE: STKitWidget/MainInterface.storyboard ================================================ ================================================ FILE: STKitWidget/STKitWidgetInHouse-Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName STKitWidget CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier com.suen.app.STKitDemo.$(PRODUCT_NAME:rfc1034identifier) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType XPC! CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 NSExtension NSExtensionMainStoryboard MainInterface NSExtensionPointIdentifier com.apple.widget-extension ================================================ FILE: STKitWidget/TodayViewController.h ================================================ // // TodayViewController.h // STKitWidget // // Created by SunJiangting on 14-10-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import @interface TodayViewController : UIViewController @end ================================================ FILE: STKitWidget/TodayViewController.m ================================================ // // TodayViewController.m // STKitWidget // // Created by SunJiangting on 14-10-9. // Copyright (c) 2014年 SunJiangting. All rights reserved. // #import "TodayViewController.h" #import #import #import "STDFeedItem.h" #import "STDBNetwork.h" @interface TodayViewController () @property (nonatomic, assign) UIEdgeInsets edgeInsets; @property (nonatomic, strong) NSArray * feeds; @property (nonatomic, strong) UIButton * prevButton, *nextButton; @property (nonatomic, strong) STLabel * titleLabel; @property (nonatomic, strong) UIImageView * imageView; @property (nonatomic, assign) NSUInteger selectedIndex; @property (nonatomic, assign) NSTimeInterval previousRequestTime; @end @implementation TodayViewController - (void)viewDidLoad { [super viewDidLoad]; NSString * cacheKey = [NSString stringWithFormat:@"%@-LastRequest", self.class].st_md5String; self.previousRequestTime = [[[STPersistence standardPersistence] valueForKey:cacheKey] doubleValue]; self.edgeInsets = UIEdgeInsetsZero; CGFloat height = 120; CGSize size = self.preferredContentSize; size.height = height; self.preferredContentSize = size; // Do any additional setup after loading the view from its nib. UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)]; imageView.st_placeholderImage = [UIImage imageNamed:@"product_default"]; imageView.contentMode = UIViewContentModeScaleAspectFill; imageView.clipsToBounds = YES; [self.view addSubview:imageView]; self.imageView = imageView; self.titleLabel = [[STLabel alloc] initWithFrame:CGRectMake(120, 10, self.view.width - 240, 100)]; self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; self.titleLabel.verticalAlignment = STVerticalAlignmentTop; self.titleLabel.textColor = [UIColor whiteColor]; self.titleLabel.font = [UIFont systemFontOfSize:16.]; self.titleLabel.numberOfLines = 0; self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping; [self.view addSubview:self.titleLabel]; UIButton * prevButton = [UIButton buttonWithType:UIButtonTypeCustom]; prevButton.frame = CGRectMake(self.view.width - 100, 30, 80, 20); [prevButton setTitle:@"上一张" forState:UIControlStateNormal]; [prevButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [prevButton addTarget:self action:@selector(displayPreviousActionFired:) forControlEvents:UIControlEventTouchUpInside]; prevButton.hidden = YES; [self.view addSubview:prevButton]; self.prevButton = prevButton; UIButton * nextButton = [UIButton buttonWithType:UIButtonTypeCustom]; nextButton.frame = CGRectMake(self.view.width - 100, 70, 80, 20); [nextButton setTitle:@"下一张" forState:UIControlStateNormal]; [nextButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [nextButton addTarget:self action:@selector(displayNextActionFired:) forControlEvents:UIControlEventTouchUpInside]; nextButton.hidden = YES; [self.view addSubview:nextButton]; self.nextButton = nextButton; [self loadDataFromCache]; const NSTimeInterval minimumTimeInterval = 5 * 60; NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970]; if ((timeInterval - self.previousRequestTime) >= minimumTimeInterval) { __weak TodayViewController * weakSelf = self; [[STDBNetwork sharedNetwork] fetchDBFeedWithMethod:@"category/2" parameters:nil completionHandler:^(NSArray *feeds, BOOL hasMore, NSError *error) { self.feeds = feeds; self.selectedIndex = 0; self.previousRequestTime = [[NSDate date] timeIntervalSince1970]; NSString * cacheKey = [NSString stringWithFormat:@"%@-LastRequest", self.class].st_md5String; [[STPersistence standardPersistence] setValue:@(weakSelf.previousRequestTime) forKey:cacheKey]; NSMutableArray * result = [NSMutableArray arrayWithCapacity:5]; [feeds enumerateObjectsUsingBlock:^(STDFeedItem * obj, NSUInteger idx, BOOL *stop) { [result addObject:[obj toDictionary]]; }]; NSString * cacheFeedsKey = [NSString stringWithFormat:@"%@-CachedData", self.class].st_md5String; [[STPersistence documentPersistence] setValue:result forKey:cacheFeedsKey]; }]; } } - (void) loadDataFromCache { NSMutableArray * result = [NSMutableArray arrayWithCapacity:5]; NSString * cacheKey = [NSString stringWithFormat:@"%@-CachedData", self.class].st_md5String; NSArray * cachedFeeds = [[STPersistence documentPersistence] valueForKey:cacheKey]; if ([cachedFeeds isKindOfClass:[NSArray class]]) { [cachedFeeds enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { STDFeedItem * feedItem = [[STDFeedItem alloc] initWithDictionary:obj]; [result addObject:feedItem]; }]; self.feeds = result; NSInteger selectedIndex = [[[STPersistence standardPersistence] valueForKey:@"CachedSelectedIndex"] integerValue]; self.selectedIndex = selectedIndex; } } - (void) displayPreviousActionFired:(id) sender { self.selectedIndex --; } - (void) displayNextActionFired:(id) sender { self.selectedIndex ++; } - (void) setSelectedIndex:(NSUInteger)selectedIndex { if (selectedIndex >= self.feeds.count) { return; } STDFeedItem * feedItem = self.feeds[selectedIndex]; [self.imageView st_setImageWithURLString:feedItem.thumbURLString]; self.titleLabel.text = feedItem.title; self.prevButton.hidden = !(selectedIndex > 0); self.nextButton.hidden = !(selectedIndex < (self.feeds.count - 1)); _selectedIndex = selectedIndex; [[STPersistence standardPersistence] setValue:@(selectedIndex) forKey:@"CachedSelectedIndex"]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler { // Perform any setup necessary in order to update the view. // If an error is encountered, use NCUpdateResultFailed // If there's no update required, use NCUpdateResultNoData // If there's an update, use NCUpdateResultNewData completionHandler(NCUpdateResultNoData); } - (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets { return self.edgeInsets; } @end