├── .gitignore ├── .travis.yml ├── Example ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── images │ ├── 1.png │ ├── 10.jpg │ ├── 2.png │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ └── 9.png └── main.m ├── LICENSE ├── README.md ├── RSUIImageViewMultiborder.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── RSUIImageViewMultiborder.xcscheme └── RSUIImageViewMultiborder ├── RSCotentModeHandler.h ├── RSCotentModeHandler.m ├── RSUIImageViewMultiborder+PropertyHandler.h ├── RSUIImageViewMultiborder+PropertyHandler.m ├── RSUIImageViewMultiborder.h └── RSUIImageViewMultiborder.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | 55 | #Code Injection 56 | # 57 | # After new code Injection tools there's a generated folder /iOSInjectionProject 58 | # https://github.com/johnno1962/injectionforxcode 59 | 60 | iOSInjectionProject/ 61 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.2 3 | script: 4 | - xcodebuild CODE_SIGNING_REQUIRED=NO -------------------------------------------------------------------------------- /Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import 22 | 23 | @interface AppDelegate : UIResponder 24 | 25 | @property (strong, nonatomic) UIWindow *window; 26 | 27 | 28 | @end 29 | 30 | -------------------------------------------------------------------------------- /Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import "AppDelegate.h" 22 | 23 | @interface AppDelegate () 24 | 25 | @end 26 | 27 | @implementation AppDelegate 28 | 29 | 30 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 31 | // Override point for customization after application launch. 32 | return YES; 33 | } 34 | 35 | 36 | - (void)applicationWillResignActive:(UIApplication *)application { 37 | // 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. 38 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 39 | } 40 | 41 | 42 | - (void)applicationDidEnterBackground:(UIApplication *)application { 43 | // 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. 44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 45 | } 46 | 47 | 48 | - (void)applicationWillEnterForeground:(UIApplication *)application { 49 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 50 | } 51 | 52 | 53 | - (void)applicationDidBecomeActive:(UIApplication *)application { 54 | // 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. 55 | } 56 | 57 | 58 | - (void)applicationWillTerminate:(UIApplication *)application { 59 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 60 | } 61 | 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 77 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | UISupportedInterfaceOrientations~ipad 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationPortraitUpsideDown 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Example/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // RSUIImageViewMultiborder 4 | // 5 | // Created by Ratul Sharker on 2/9/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // RSUIImageViewMultiborder 4 | // 5 | // Created by Ratul Sharker on 2/9/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | 23 | - (void)didReceiveMemoryWarning { 24 | [super didReceiveMemoryWarning]; 25 | // Dispose of any resources that can be recreated. 26 | } 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Example/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/1.png -------------------------------------------------------------------------------- /Example/images/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/10.jpg -------------------------------------------------------------------------------- /Example/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/2.png -------------------------------------------------------------------------------- /Example/images/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/3.jpg -------------------------------------------------------------------------------- /Example/images/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/4.jpg -------------------------------------------------------------------------------- /Example/images/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/5.jpg -------------------------------------------------------------------------------- /Example/images/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/6.jpg -------------------------------------------------------------------------------- /Example/images/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/7.jpg -------------------------------------------------------------------------------- /Example/images/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/8.jpg -------------------------------------------------------------------------------- /Example/images/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ratulSharker/RSUIImageViewMultiborder/d148dd319e851066ef94992674559c9a67433bea/Example/images/9.png -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RSUIImageViewMultiborder 4 | // 5 | // Created by Ratul Sharker on 2/9/17. 6 | // Copyright © 2017 funtoos. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ratul sharker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | codebeat badge 5 | [![Build Status](https://travis-ci.org/ratulSharker/RSUIImageViewMultiborder.svg?branch=master)](https://travis-ci.org/ratulSharker/RSUIImageViewMultiborder) 6 | [![Language](https://img.shields.io/badge/language-obj--c-orange.svg)](https://en.wikipedia.org/wiki/IOS) 7 | [![Platform](https://img.shields.io/badge/platform-ios-green.svg)](https://en.wikipedia.org/wiki/IOS) 8 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) 9 | 10 | # Quick Demo 11 | Demo 12 | 13 | 14 | # Background 15 | Customising ios application are quiet challenging when there is no apple provided user interface or api to do that. Showing multiple border alongside the shown image is one of that. Like following: 16 | 17 | Sample bordererd image 18 | 19 | To achieve that we have to put `UIImageView` inside an `UIView` as a sub-view and changing the container view's background color. Another way to achive is to subclass the `UIImageView` and implement the `drawRect:` method to draw whatever we need. But apple discourages to implement the `drawRect:`, and even they didn't executes your `drawRect:` implementation. 20 | 21 | Directly from the [appledoc](https://developer.apple.com/reference/uikit/uiimageview?language=objc) 22 | 23 | >### Do not use image views for custom drawing. 24 | TheUIImageView class does not draw its content using the drawRect: method. Use image views only to present images. To do custom drawing involving images, subclass UIView directly and draw your image there. 25 | 26 | So here it is, `UIView` is subclassed and the `UIImage` is drawn inside with proper content mode specified, maintaining specified number of border. 27 | 28 | # Installation 29 | Copy the class named [`RSUIImageViewMultiborder`](https://github.com/ratulSharker/RSUIImageViewMultiborder/tree/master/RSUIImageViewMultiborder), a category file and [`RSCotentModeHandler`](https://github.com/ratulSharker/RSUIImageViewMultiborder/tree/master/RSCotentModeHandler) . In interface builder take an `UIView` and set the custom class as `RSUIImageViewMultiborder`. 30 | 31 | `RSUIImageViewCustomBadge` will be available through cocoapod soon. 32 | 33 | # Customizing 34 | Adding a new border is the most easiest part. To add a new border in `RSUIImageViewCustomBadge.h` add two property of the following format 35 | 36 | ```objective-c 37 | @property IBInspectable UIColor *border_color_xxx; 38 | @property IBInspectable CGFloat border_width_xxx; 39 | ``` 40 | 41 | which represents a border. 42 | 43 | Things we needed to take into account, is that, the border declaration preceedes the other border are rendered in the outer section from other border. For example 44 | 45 | ```objective-c 46 | @property IBInspectable UIColor *border_color_1; //first border - the outmost border 47 | @property IBInspectable CGFloat border_width_1; 48 | 49 | @property IBInspectable UIColor *border_color_2; //second border 50 | @property IBInspectable CGFloat border_width_2; 51 | 52 | @property IBInspectable UIColor *border_color_3; //third border from the outmost border 53 | @property IBInspectable CGFloat border_width_3; 54 | 55 | @property IBInspectable UIColor *border_color_4; //fourth border 56 | @property IBInspectable CGFloat border_width_4; 57 | ``` 58 | 59 | so find the appropriate position of the border, where to add it and feel free to delete any unnecessary border you are not using. Deleting a border requires to delete two property indicating a border. 60 | 61 | # Properties 62 | `RSUIImageViewMultiborder` has following properties 63 | 64 | |Property |Type |Denotes | 65 | |:--------------------|:------------------|:------------------------------------------------| 66 | |isRounded |BOOL |set the corner radius to it's half of it's width | 67 | |border_color_xxx |UIColor |designate the color of a border | 68 | |border_width_xxx |CGFloat |the width of the border | 69 | |image |UIImage |image to be rendered | 70 | |contentMode |UIViewContentMode |actually the property contentMode is shared from UIView, which determine the render mode of the image property| 71 | 72 | 73 | # Features 74 | There are several features which are not ready yet. Features completed are marked. 75 | 76 | - [X] CI-integration. 77 | - [X] Support rounded and non-rounded regular border. 78 | - [X] Support IBDesignable to be customized from interface builder. 79 | - [X] Adding a border just adding necessary properties. 80 | - [X] Handle image drawing for all content mode. 81 | - [ ] Available in cocoapod. 82 | - [ ] Finding a cleaner way to add border while installed via cocoapod. 83 | - [ ] Supporting line drawing style in interface builder (i.e dotted line, rounded dotted line etc). 84 | 85 | # License 86 | 87 | RSUIImageViewMultiborder is available under the MIT license. See the [LICENSE](https://github.com/ratulSharker/RSUIImageViewMultiborder/blob/master/LICENSE) file for more info. 88 | 89 | Please feel free to file an [issue](https://github.com/ratulSharker/RSUIImageViewMultiborder/issues), on any inconsistency found or new feature needed. 90 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E742E3E71E4CBF1D0077840D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E742E3DA1E4CBF1D0077840D /* AppDelegate.m */; }; 11 | E742E3E81E4CBF1D0077840D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E742E3DB1E4CBF1D0077840D /* Assets.xcassets */; }; 12 | E742E3E91E4CBF1D0077840D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E742E3DC1E4CBF1D0077840D /* LaunchScreen.storyboard */; }; 13 | E742E3EA1E4CBF1D0077840D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E742E3DE1E4CBF1D0077840D /* Main.storyboard */; }; 14 | E742E3EB1E4CBF1D0077840D /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = E742E3E01E4CBF1D0077840D /* Info.plist */; }; 15 | E742E3EC1E4CBF1D0077840D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E742E3E11E4CBF1D0077840D /* main.m */; }; 16 | E742E3ED1E4CBF1D0077840D /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E742E3E31E4CBF1D0077840D /* ViewController.m */; }; 17 | E742E3EE1E4CBF1D0077840D /* RSUIImageViewMultiborder.m in Sources */ = {isa = PBXBuildFile; fileRef = E742E3E61E4CBF1D0077840D /* RSUIImageViewMultiborder.m */; }; 18 | E752C4201E4F05160038F8F5 /* 1.png in Resources */ = {isa = PBXBuildFile; fileRef = E752C4161E4F05160038F8F5 /* 1.png */; }; 19 | E752C4211E4F05160038F8F5 /* 2.png in Resources */ = {isa = PBXBuildFile; fileRef = E752C4171E4F05160038F8F5 /* 2.png */; }; 20 | E752C4221E4F05160038F8F5 /* 3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C4181E4F05160038F8F5 /* 3.jpg */; }; 21 | E752C4231E4F05160038F8F5 /* 4.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C4191E4F05160038F8F5 /* 4.jpg */; }; 22 | E752C4241E4F05160038F8F5 /* 5.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C41A1E4F05160038F8F5 /* 5.jpg */; }; 23 | E752C4251E4F05160038F8F5 /* 6.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C41B1E4F05160038F8F5 /* 6.jpg */; }; 24 | E752C4261E4F05160038F8F5 /* 7.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C41C1E4F05160038F8F5 /* 7.jpg */; }; 25 | E752C4271E4F05160038F8F5 /* 8.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C41D1E4F05160038F8F5 /* 8.jpg */; }; 26 | E752C4281E4F05160038F8F5 /* 9.png in Resources */ = {isa = PBXBuildFile; fileRef = E752C41E1E4F05160038F8F5 /* 9.png */; }; 27 | E752C4291E4F05160038F8F5 /* 10.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E752C41F1E4F05160038F8F5 /* 10.jpg */; }; 28 | E774055C1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E774055B1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.m */; }; 29 | E774055F1E5B518D008DBB93 /* RSCotentModeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = E774055E1E5B518D008DBB93 /* RSCotentModeHandler.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | E742E3BE1E4CBEBE0077840D /* RSUIImageViewMultiborder.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RSUIImageViewMultiborder.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | E742E3D91E4CBF1D0077840D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | E742E3DA1E4CBF1D0077840D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | E742E3DB1E4CBF1D0077840D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 37 | E742E3DD1E4CBF1D0077840D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 38 | E742E3DF1E4CBF1D0077840D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | E742E3E01E4CBF1D0077840D /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | E742E3E11E4CBF1D0077840D /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | E742E3E21E4CBF1D0077840D /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 42 | E742E3E31E4CBF1D0077840D /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 43 | E742E3E51E4CBF1D0077840D /* RSUIImageViewMultiborder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSUIImageViewMultiborder.h; sourceTree = ""; }; 44 | E742E3E61E4CBF1D0077840D /* RSUIImageViewMultiborder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSUIImageViewMultiborder.m; sourceTree = ""; }; 45 | E752C4161E4F05160038F8F5 /* 1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 1.png; sourceTree = ""; }; 46 | E752C4171E4F05160038F8F5 /* 2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 2.png; sourceTree = ""; }; 47 | E752C4181E4F05160038F8F5 /* 3.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 3.jpg; sourceTree = ""; }; 48 | E752C4191E4F05160038F8F5 /* 4.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 4.jpg; sourceTree = ""; }; 49 | E752C41A1E4F05160038F8F5 /* 5.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 5.jpg; sourceTree = ""; }; 50 | E752C41B1E4F05160038F8F5 /* 6.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 6.jpg; sourceTree = ""; }; 51 | E752C41C1E4F05160038F8F5 /* 7.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 7.jpg; sourceTree = ""; }; 52 | E752C41D1E4F05160038F8F5 /* 8.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 8.jpg; sourceTree = ""; }; 53 | E752C41E1E4F05160038F8F5 /* 9.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 9.png; sourceTree = ""; }; 54 | E752C41F1E4F05160038F8F5 /* 10.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 10.jpg; sourceTree = ""; }; 55 | E774055A1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "RSUIImageViewMultiborder+PropertyHandler.h"; sourceTree = ""; }; 56 | E774055B1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RSUIImageViewMultiborder+PropertyHandler.m"; sourceTree = ""; }; 57 | E774055D1E5B518D008DBB93 /* RSCotentModeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSCotentModeHandler.h; sourceTree = ""; }; 58 | E774055E1E5B518D008DBB93 /* RSCotentModeHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSCotentModeHandler.m; sourceTree = ""; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | E742E3BB1E4CBEBE0077840D /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | ); 67 | runOnlyForDeploymentPostprocessing = 0; 68 | }; 69 | /* End PBXFrameworksBuildPhase section */ 70 | 71 | /* Begin PBXGroup section */ 72 | E742E3B51E4CBEBE0077840D = { 73 | isa = PBXGroup; 74 | children = ( 75 | E742E3E41E4CBF1D0077840D /* RSUIImageViewMultiborder */, 76 | E742E3D81E4CBF1D0077840D /* Example */, 77 | E742E3BF1E4CBEBE0077840D /* Products */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | E742E3BF1E4CBEBE0077840D /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | E742E3BE1E4CBEBE0077840D /* RSUIImageViewMultiborder.app */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | E742E3D81E4CBF1D0077840D /* Example */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | E742E3F01E4CC4E00077840D /* images */, 93 | E742E3D91E4CBF1D0077840D /* AppDelegate.h */, 94 | E742E3DA1E4CBF1D0077840D /* AppDelegate.m */, 95 | E742E3DE1E4CBF1D0077840D /* Main.storyboard */, 96 | E742E3E21E4CBF1D0077840D /* ViewController.h */, 97 | E742E3E31E4CBF1D0077840D /* ViewController.m */, 98 | E742E3DB1E4CBF1D0077840D /* Assets.xcassets */, 99 | E742E3EF1E4CBF300077840D /* Supporting Files */, 100 | ); 101 | path = Example; 102 | sourceTree = ""; 103 | }; 104 | E742E3E41E4CBF1D0077840D /* RSUIImageViewMultiborder */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | E742E3E51E4CBF1D0077840D /* RSUIImageViewMultiborder.h */, 108 | E742E3E61E4CBF1D0077840D /* RSUIImageViewMultiborder.m */, 109 | E774055A1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.h */, 110 | E774055B1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.m */, 111 | E774055D1E5B518D008DBB93 /* RSCotentModeHandler.h */, 112 | E774055E1E5B518D008DBB93 /* RSCotentModeHandler.m */, 113 | ); 114 | path = RSUIImageViewMultiborder; 115 | sourceTree = ""; 116 | }; 117 | E742E3EF1E4CBF300077840D /* Supporting Files */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | E742E3DC1E4CBF1D0077840D /* LaunchScreen.storyboard */, 121 | E742E3E01E4CBF1D0077840D /* Info.plist */, 122 | E742E3E11E4CBF1D0077840D /* main.m */, 123 | ); 124 | name = "Supporting Files"; 125 | sourceTree = ""; 126 | }; 127 | E742E3F01E4CC4E00077840D /* images */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | E752C4161E4F05160038F8F5 /* 1.png */, 131 | E752C4171E4F05160038F8F5 /* 2.png */, 132 | E752C4181E4F05160038F8F5 /* 3.jpg */, 133 | E752C4191E4F05160038F8F5 /* 4.jpg */, 134 | E752C41A1E4F05160038F8F5 /* 5.jpg */, 135 | E752C41B1E4F05160038F8F5 /* 6.jpg */, 136 | E752C41C1E4F05160038F8F5 /* 7.jpg */, 137 | E752C41D1E4F05160038F8F5 /* 8.jpg */, 138 | E752C41E1E4F05160038F8F5 /* 9.png */, 139 | E752C41F1E4F05160038F8F5 /* 10.jpg */, 140 | ); 141 | path = images; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | E742E3BD1E4CBEBE0077840D /* RSUIImageViewMultiborder */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = E742E3D51E4CBEBE0077840D /* Build configuration list for PBXNativeTarget "RSUIImageViewMultiborder" */; 150 | buildPhases = ( 151 | E742E3BA1E4CBEBE0077840D /* Sources */, 152 | E742E3BB1E4CBEBE0077840D /* Frameworks */, 153 | E742E3BC1E4CBEBE0077840D /* Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | ); 159 | name = RSUIImageViewMultiborder; 160 | productName = RSUIImageViewMultiborder; 161 | productReference = E742E3BE1E4CBEBE0077840D /* RSUIImageViewMultiborder.app */; 162 | productType = "com.apple.product-type.application"; 163 | }; 164 | /* End PBXNativeTarget section */ 165 | 166 | /* Begin PBXProject section */ 167 | E742E3B61E4CBEBE0077840D /* Project object */ = { 168 | isa = PBXProject; 169 | attributes = { 170 | LastUpgradeCheck = 0820; 171 | ORGANIZATIONNAME = funtoos; 172 | TargetAttributes = { 173 | E742E3BD1E4CBEBE0077840D = { 174 | CreatedOnToolsVersion = 8.2.1; 175 | ProvisioningStyle = Manual; 176 | }; 177 | }; 178 | }; 179 | buildConfigurationList = E742E3B91E4CBEBE0077840D /* Build configuration list for PBXProject "RSUIImageViewMultiborder" */; 180 | compatibilityVersion = "Xcode 3.2"; 181 | developmentRegion = English; 182 | hasScannedForEncodings = 0; 183 | knownRegions = ( 184 | en, 185 | Base, 186 | ); 187 | mainGroup = E742E3B51E4CBEBE0077840D; 188 | productRefGroup = E742E3BF1E4CBEBE0077840D /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | E742E3BD1E4CBEBE0077840D /* RSUIImageViewMultiborder */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | E742E3BC1E4CBEBE0077840D /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | E752C4271E4F05160038F8F5 /* 8.jpg in Resources */, 203 | E752C4261E4F05160038F8F5 /* 7.jpg in Resources */, 204 | E752C4231E4F05160038F8F5 /* 4.jpg in Resources */, 205 | E752C4211E4F05160038F8F5 /* 2.png in Resources */, 206 | E752C4281E4F05160038F8F5 /* 9.png in Resources */, 207 | E742E3EB1E4CBF1D0077840D /* Info.plist in Resources */, 208 | E752C4241E4F05160038F8F5 /* 5.jpg in Resources */, 209 | E752C4251E4F05160038F8F5 /* 6.jpg in Resources */, 210 | E752C4291E4F05160038F8F5 /* 10.jpg in Resources */, 211 | E742E3EA1E4CBF1D0077840D /* Main.storyboard in Resources */, 212 | E742E3E81E4CBF1D0077840D /* Assets.xcassets in Resources */, 213 | E742E3E91E4CBF1D0077840D /* LaunchScreen.storyboard in Resources */, 214 | E752C4221E4F05160038F8F5 /* 3.jpg in Resources */, 215 | E752C4201E4F05160038F8F5 /* 1.png in Resources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXResourcesBuildPhase section */ 220 | 221 | /* Begin PBXSourcesBuildPhase section */ 222 | E742E3BA1E4CBEBE0077840D /* Sources */ = { 223 | isa = PBXSourcesBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | E742E3ED1E4CBF1D0077840D /* ViewController.m in Sources */, 227 | E742E3EC1E4CBF1D0077840D /* main.m in Sources */, 228 | E742E3E71E4CBF1D0077840D /* AppDelegate.m in Sources */, 229 | E774055C1E5B4E94008DBB93 /* RSUIImageViewMultiborder+PropertyHandler.m in Sources */, 230 | E742E3EE1E4CBF1D0077840D /* RSUIImageViewMultiborder.m in Sources */, 231 | E774055F1E5B518D008DBB93 /* RSCotentModeHandler.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | E742E3DC1E4CBF1D0077840D /* LaunchScreen.storyboard */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | E742E3DD1E4CBF1D0077840D /* Base */, 242 | ); 243 | name = LaunchScreen.storyboard; 244 | sourceTree = ""; 245 | }; 246 | E742E3DE1E4CBF1D0077840D /* Main.storyboard */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | E742E3DF1E4CBF1D0077840D /* Base */, 250 | ); 251 | name = Main.storyboard; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXVariantGroup section */ 255 | 256 | /* Begin XCBuildConfiguration section */ 257 | E742E3D31E4CBEBE0077840D /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_WARN_BOOL_CONVERSION = YES; 267 | CLANG_WARN_CONSTANT_CONVERSION = YES; 268 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 269 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 275 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = dwarf; 281 | ENABLE_STRICT_OBJC_MSGSEND = YES; 282 | ENABLE_TESTABILITY = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu99; 284 | GCC_DYNAMIC_NO_PIC = NO; 285 | GCC_NO_COMMON_BLOCKS = YES; 286 | GCC_OPTIMIZATION_LEVEL = 0; 287 | GCC_PREPROCESSOR_DEFINITIONS = ( 288 | "DEBUG=1", 289 | "$(inherited)", 290 | ); 291 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 292 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 293 | GCC_WARN_UNDECLARED_SELECTOR = YES; 294 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 295 | GCC_WARN_UNUSED_FUNCTION = YES; 296 | GCC_WARN_UNUSED_VARIABLE = YES; 297 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 298 | MTL_ENABLE_DEBUG_INFO = YES; 299 | ONLY_ACTIVE_ARCH = YES; 300 | SDKROOT = iphoneos; 301 | TARGETED_DEVICE_FAMILY = "1,2"; 302 | }; 303 | name = Debug; 304 | }; 305 | E742E3D41E4CBEBE0077840D /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 311 | CLANG_CXX_LIBRARY = "libc++"; 312 | CLANG_ENABLE_MODULES = YES; 313 | CLANG_ENABLE_OBJC_ARC = YES; 314 | CLANG_WARN_BOOL_CONVERSION = YES; 315 | CLANG_WARN_CONSTANT_CONVERSION = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 318 | CLANG_WARN_EMPTY_BODY = YES; 319 | CLANG_WARN_ENUM_CONVERSION = YES; 320 | CLANG_WARN_INFINITE_RECURSION = YES; 321 | CLANG_WARN_INT_CONVERSION = YES; 322 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 323 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 324 | CLANG_WARN_UNREACHABLE_CODE = YES; 325 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 326 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 327 | COPY_PHASE_STRIP = NO; 328 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 329 | ENABLE_NS_ASSERTIONS = NO; 330 | ENABLE_STRICT_OBJC_MSGSEND = YES; 331 | GCC_C_LANGUAGE_STANDARD = gnu99; 332 | GCC_NO_COMMON_BLOCKS = YES; 333 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 334 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 335 | GCC_WARN_UNDECLARED_SELECTOR = YES; 336 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 337 | GCC_WARN_UNUSED_FUNCTION = YES; 338 | GCC_WARN_UNUSED_VARIABLE = YES; 339 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 340 | MTL_ENABLE_DEBUG_INFO = NO; 341 | SDKROOT = iphoneos; 342 | TARGETED_DEVICE_FAMILY = "1,2"; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | E742E3D61E4CBEBE0077840D /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 351 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 352 | DEVELOPMENT_TEAM = ""; 353 | INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist"; 354 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 356 | PRODUCT_BUNDLE_IDENTIFIER = com.RSUIImageViewMultiborder; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | TARGETED_DEVICE_FAMILY = 1; 359 | }; 360 | name = Debug; 361 | }; 362 | E742E3D71E4CBEBE0077840D /* Release */ = { 363 | isa = XCBuildConfiguration; 364 | buildSettings = { 365 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 366 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 367 | DEVELOPMENT_TEAM = ""; 368 | INFOPLIST_FILE = "$(SRCROOT)/Example/Info.plist"; 369 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 370 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 371 | PRODUCT_BUNDLE_IDENTIFIER = com.RSUIImageViewMultiborder; 372 | PRODUCT_NAME = "$(TARGET_NAME)"; 373 | TARGETED_DEVICE_FAMILY = 1; 374 | }; 375 | name = Release; 376 | }; 377 | /* End XCBuildConfiguration section */ 378 | 379 | /* Begin XCConfigurationList section */ 380 | E742E3B91E4CBEBE0077840D /* Build configuration list for PBXProject "RSUIImageViewMultiborder" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | E742E3D31E4CBEBE0077840D /* Debug */, 384 | E742E3D41E4CBEBE0077840D /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | E742E3D51E4CBEBE0077840D /* Build configuration list for PBXNativeTarget "RSUIImageViewMultiborder" */ = { 390 | isa = XCConfigurationList; 391 | buildConfigurations = ( 392 | E742E3D61E4CBEBE0077840D /* Debug */, 393 | E742E3D71E4CBEBE0077840D /* Release */, 394 | ); 395 | defaultConfigurationIsVisible = 0; 396 | defaultConfigurationName = Release; 397 | }; 398 | /* End XCConfigurationList section */ 399 | }; 400 | rootObject = E742E3B61E4CBEBE0077840D /* Project object */; 401 | } 402 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder.xcodeproj/xcshareddata/xcschemes/RSUIImageViewMultiborder.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSCotentModeHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import 22 | 23 | @interface RSCotentModeHandler : NSObject 24 | 25 | /** 26 | * Get an resized image according to the content mode in a given rect 27 | * 28 | * @param 29 | * image - which is needed to be resized according to content mode 30 | * contentMode - expected content mode for the image 31 | * rect - designated rectangle for the image to be rendered 32 | */ 33 | + (UIImage*)getImageForUIImage:(UIImage*)image 34 | contentMode:(UIViewContentMode)contentMode 35 | forRect:(CGRect)rect; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSCotentModeHandler.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import "RSCotentModeHandler.h" 22 | 23 | @implementation RSCotentModeHandler 24 | 25 | 26 | /** 27 | * Get an resized image according to the content mode in a given rect 28 | * 29 | * @param 30 | * image - which is needed to be resized according to content mode 31 | * contentMode - expected content mode for the image 32 | * rect - designated rectangle for the image to be rendered 33 | */ 34 | + (UIImage*)getImageForUIImage:(UIImage*)image 35 | contentMode:(UIViewContentMode)contentMode 36 | forRect:(CGRect)rect 37 | { 38 | switch (contentMode) { 39 | 40 | 41 | case UIViewContentModeScaleAspectFill : case UIViewContentModeScaleAspectFit: 42 | // contents scaled to fit with fixed aspect. remainder is transparent 43 | return [self handleAspectFillOrFitContentMode:contentMode forImage:image forRect:rect]; 44 | 45 | //all center modes 46 | case UIViewContentModeCenter : case UIViewContentModeTop: case UIViewContentModeBottom: 47 | return [self handleAllCenterContentMode:contentMode forImage:image forRect:rect]; 48 | 49 | //all left modes 50 | case UIViewContentModeLeft: case UIViewContentModeTopLeft: case UIViewContentModeBottomLeft: 51 | return [self handleAllLeftContentMode:contentMode forImage:image forRect:rect]; 52 | 53 | //all right modes 54 | case UIViewContentModeRight: case UIViewContentModeTopRight: case UIViewContentModeBottomRight: 55 | return [self handleAllRightContentMode:contentMode forImage:image forRect:rect]; 56 | 57 | //unchanged 58 | case UIViewContentModeRedraw: case UIViewContentModeScaleToFill: 59 | return image; 60 | } 61 | } 62 | 63 | 64 | #pragma mark private image content mode maintainer method 65 | /** 66 | * Handle the two major content mode in a separate function. 67 | * 68 | * @param 69 | * contentMode - supported mode is AspectFit or AspectFill. 70 | * image - image which needed to be rendered. 71 | * rect - destination rect. 72 | */ 73 | + (UIImage*)handleAspectFillOrFitContentMode:(UIViewContentMode)contentMode 74 | forImage:(UIImage*)image 75 | forRect:(CGRect)rect 76 | { 77 | CGFloat heightRatio = image.size.height / CGRectGetHeight(rect); 78 | CGFloat widthRatio = image.size.width / CGRectGetWidth(rect); 79 | 80 | CGFloat maxRatio = (contentMode == UIViewContentModeScaleAspectFit) ? 81 | MAX(heightRatio, widthRatio) : MIN(heightRatio, widthRatio); 82 | 83 | CGRect resultedImageRect = CGRectMake(0, 84 | 0, 85 | image.size.width / maxRatio, 86 | image.size.height / maxRatio); 87 | 88 | resultedImageRect = CGRectOffset(resultedImageRect, 89 | CGRectGetMidX(rect) - CGRectGetMidX(resultedImageRect), 90 | CGRectGetMidY(rect) - CGRectGetMidY(resultedImageRect)); 91 | 92 | return [self getImage:image 93 | drawnOnRect:rect.size 94 | withImageRect:resultedImageRect]; 95 | } 96 | 97 | /** 98 | * Handle all left type content modes like following 99 | * - UIViewContentModeTopLeft 100 | * - UIViewContentModeLeft 101 | * - UIViewContentModeBottomLeft 102 | * 103 | * @param 104 | * contentMode - specified content mode among the listed 105 | * image - image which is about to be resized 106 | * rect - container rect, where the image will be rendered 107 | */ 108 | + (UIImage*)handleAllLeftContentMode:(UIViewContentMode)contentMode 109 | forImage:(UIImage*)image 110 | forRect:(CGRect)rect 111 | { 112 | CGRect imageDrawnRect = CGRectMake(0, 0, image.size.width, image.size.height); 113 | CGFloat fullHeight = (CGRectGetHeight(rect) - CGRectGetHeight(imageDrawnRect)); 114 | switch (contentMode) { 115 | case UIViewContentModeLeft: 116 | // center left 117 | // only need to modify y position of the rect to half way 118 | imageDrawnRect.origin.y = fullHeight / 2.0; 119 | break; 120 | case UIViewContentModeBottomLeft: 121 | // left bottom position 122 | // need to modify y in this case in full way 123 | imageDrawnRect.origin.y = fullHeight; 124 | break; 125 | // case UIViewContentModeTopLeft: 126 | // //nothing to do 127 | // break; 128 | default: 129 | break; 130 | } 131 | 132 | return [self getImage:image drawnOnRect:rect.size withImageRect:imageDrawnRect]; 133 | } 134 | 135 | /** 136 | * Handle all center type content modes like following 137 | * - UIViewContentModeTop 138 | * - UIViewContentModeCenter 139 | * - UIViewContentModeBottom 140 | * 141 | * @param 142 | * contentMode - specified content mode among the listed 143 | * image - image which is about to be resized 144 | * rect - container rect, where the image will be rendered 145 | */ 146 | + (UIImage*)handleAllCenterContentMode:(UIViewContentMode)contentMode 147 | forImage:(UIImage*)image 148 | forRect:(CGRect)rect 149 | { 150 | CGRect imageDrawnRect = CGRectMake(0, 0, image.size.width, image.size.height); 151 | CGFloat fullHeight = (CGRectGetHeight(rect) - CGRectGetHeight(imageDrawnRect)); 152 | imageDrawnRect.origin.x = (CGRectGetWidth(rect) - CGRectGetWidth(imageDrawnRect)) / 2.0; 153 | switch (contentMode) { 154 | // case UIViewContentModeTop: 155 | // // top center 156 | // // only need to modify x position of the rect to half way 157 | // imageDrawnRect.origin.x = fullWidth / 2.0; 158 | // break; 159 | case UIViewContentModeCenter: 160 | // center position 161 | // need to modify x and y both half way 162 | // imageDrawnRect.origin.x = fullWidth / 2.0; 163 | imageDrawnRect.origin.y = fullHeight / 2.0; 164 | break; 165 | case UIViewContentModeBottom: 166 | // center bottom position 167 | // need to modify x and y both in this case 168 | // modify x half way 169 | // modify y full way 170 | // imageDrawnRect.origin.x = fullWidth / 2.0; 171 | imageDrawnRect.origin.y = fullHeight; 172 | break; 173 | default: 174 | break; 175 | } 176 | 177 | return [self getImage:image drawnOnRect:rect.size withImageRect:imageDrawnRect]; 178 | } 179 | 180 | /** 181 | * Handle all right type content modes like following 182 | * - UIViewContentModeTopRight 183 | * - UIViewContentModeRight 184 | * - UIViewContentModeBottomRight 185 | * 186 | * @param 187 | * contentMode - specified content mode among the listed 188 | * image - image which is about to be resized 189 | * rect - container rect, where the image will be rendered 190 | */ 191 | + (UIImage*)handleAllRightContentMode:(UIViewContentMode)contentMode 192 | forImage:(UIImage*)image 193 | forRect:(CGRect)rect 194 | { 195 | CGRect imageDrawnRect = CGRectMake(0, 0, image.size.width, image.size.height); 196 | CGFloat fullHeight = (CGRectGetHeight(rect) - CGRectGetHeight(imageDrawnRect)); 197 | imageDrawnRect.origin.x = (CGRectGetWidth(rect) - CGRectGetWidth(imageDrawnRect)); 198 | 199 | switch (contentMode) { 200 | // case UIViewContentModeTopRight: 201 | // // top right most position 202 | // // only need to modify x position of the rect to full way 203 | // imageDrawnRect.origin.x = fullWidth; 204 | // break; 205 | case UIViewContentModeRight: 206 | // center right position 207 | // need to modify x and y both, but in this case 208 | // modify x full way 209 | // modify y half way 210 | // imageDrawnRect.origin.x = fullWidth; 211 | imageDrawnRect.origin.y = fullHeight / 2.0; 212 | break; 213 | case UIViewContentModeBottomRight: 214 | // right bottom position 215 | // need to modify both x and y, both will be full way through 216 | // imageDrawnRect.origin.x = fullWidth; 217 | imageDrawnRect.origin.y = fullHeight; 218 | break; 219 | default: 220 | break; 221 | } 222 | return [self getImage:image drawnOnRect:rect.size withImageRect:imageDrawnRect]; 223 | } 224 | 225 | /** 226 | * Get an image drawn with a given canvas size and given image size 227 | * 228 | * @param 229 | * image - which will be resized 230 | * canvasSize - whole size of the canvas 231 | * imageRect - Rect of the image which define both size of the image and the position in the canvas 232 | */ 233 | + (UIImage*)getImage:(UIImage*)image 234 | drawnOnRect:(CGSize)canvasSize 235 | withImageRect:(CGRect)imageRect 236 | { 237 | //UIGraphicsBeginImageContext(rect.size); 238 | // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution). 239 | // Pass 1.0 to force exact pixel size. 240 | UIGraphicsBeginImageContextWithOptions(canvasSize, NO, 0.0); 241 | [image drawInRect:imageRect]; 242 | 243 | UIImage *resultedImage = UIGraphicsGetImageFromCurrentImageContext(); 244 | UIGraphicsEndImageContext();; 245 | return resultedImage; 246 | } 247 | 248 | @end 249 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSUIImageViewMultiborder+PropertyHandler.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import "RSUIImageViewMultiborder.h" 22 | 23 | @interface RSUIImageViewMultiborder (PropertyHandler) 24 | 25 | /** 26 | * Get the total number of border count 27 | * it asserts on the total declared property 28 | */ 29 | + (NSUInteger)getBorderCount; 30 | 31 | /** 32 | * Get the border color of a particular border 33 | * indexed via the parameter index. 34 | */ 35 | - (UIColor*)getBorderColorAtIndex:(NSUInteger)index; 36 | 37 | /** 38 | * Get the border width of a particular border 39 | * indexed via the parameter index. 40 | */ 41 | - (CGFloat)getBorderWidthAtIndex:(NSUInteger)index; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSUIImageViewMultiborder+PropertyHandler.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import "RSUIImageViewMultiborder+PropertyHandler.h" 22 | //#import //this header is only available to simulator SDK 23 | #import 24 | 25 | @implementation RSUIImageViewMultiborder (PropertyHandler) 26 | 27 | static NSArray *borderColorPropertyNames; 28 | static NSArray *borderWidthPropertyNames; 29 | 30 | /** 31 | * Get the total number of border count 32 | * it asserts on the total declared property 33 | */ 34 | + (NSUInteger)getBorderCount 35 | { 36 | NSAssert(borderColorPropertyNames.count == borderWidthPropertyNames.count, @"inequal number of border-color and border-width property"); 37 | 38 | return borderColorPropertyNames.count; 39 | } 40 | 41 | /** 42 | * Get the border color of a particular border 43 | * indexed via the parameter index. 44 | */ 45 | - (UIColor*)getBorderColorAtIndex:(NSUInteger)index 46 | { 47 | NSAssert(index < [self.class getBorderCount], @"array index out of bound for color access"); 48 | NSString *propertyName = borderColorPropertyNames[index]; 49 | return [self valueForKey:propertyName]; 50 | } 51 | 52 | /** 53 | * Get the border width of a particular border 54 | * indexed via the parameter index. 55 | */ 56 | - (CGFloat)getBorderWidthAtIndex:(NSUInteger)index 57 | { 58 | NSAssert(index < [self.class getBorderCount], @"array index out of bound for width access"); 59 | NSString *propertyName = borderWidthPropertyNames[index]; 60 | return [[self valueForKey:propertyName] doubleValue]; 61 | } 62 | 63 | /** 64 | * while the class loads, this method is fired, instead of generating 65 | * property names each time the view invalidates, pre-calculate the 66 | * property list will enhance performance. 67 | */ 68 | + (void)load 69 | { 70 | NSArray *allPropertyNames = [self allPropertyNames]; 71 | borderColorPropertyNames = [allPropertyNames filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF beginswith 'border_color'"]]; 72 | borderWidthPropertyNames = [allPropertyNames filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF beginswith 'border_width'"]]; 73 | } 74 | 75 | /** 76 | * Get the list of all properties of this class 77 | */ 78 | + (NSArray *)allPropertyNames 79 | { 80 | unsigned count; 81 | objc_property_t *properties = class_copyPropertyList([self class], &count); 82 | NSMutableArray *rv = [NSMutableArray array]; 83 | 84 | unsigned i; 85 | for (i = 0; i < count; i++) 86 | { 87 | objc_property_t property = properties[i]; 88 | NSString *name = [NSString stringWithUTF8String:property_getName(property)]; 89 | [rv addObject:name]; 90 | } 91 | 92 | free(properties); 93 | 94 | return [NSArray arrayWithArray:rv]; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSUIImageViewMultiborder.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import 22 | 23 | 24 | IB_DESIGNABLE 25 | @interface RSUIImageViewMultiborder : UIView 26 | 27 | /** 28 | * Decide's, is the view will shaped rounded or not 29 | */ 30 | @property IBInspectable BOOL isRounded; 31 | 32 | 33 | /** 34 | * Here declared two property in pair 35 | * 1. border_color_xxx 36 | * 2. border_width_xxx 37 | * 38 | * Each property pair represent's a border. First property represent the 39 | * UIColor of the border and the second property declare the width of the 40 | * border. The border declared in first position are to be rendered in 41 | * most outer border, and border declared later are to be rendered 42 | * inside the previous one. 43 | * 44 | * To add a new border you have to do two thing right. 45 | * 1. find the position of the border (after which border it will be placed) 46 | * 2. declare two property of following format 47 | 48 | @property IBInspectable UIColor *border_color_xxx; 49 | @property IBInspectable CGFloat border_width_xxx; 50 | * 51 | * it will eventually appear in the interface builder. 52 | * 53 | */ 54 | @property IBInspectable UIColor *border_color_1; 55 | @property IBInspectable CGFloat border_width_1; 56 | 57 | @property IBInspectable UIColor *border_color_2; 58 | @property IBInspectable CGFloat border_width_2; 59 | 60 | @property IBInspectable UIColor *border_color_3; 61 | @property IBInspectable CGFloat border_width_3; 62 | 63 | @property IBInspectable UIColor *border_color_4; 64 | @property IBInspectable CGFloat border_width_4; 65 | 66 | /** 67 | * UIImage which will be rendered 68 | */ 69 | @property IBInspectable UIImage *image; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /RSUIImageViewMultiborder/RSUIImageViewMultiborder.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017 Ratul sharker 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all 11 | // copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | // SOFTWARE. 20 | 21 | #import "RSUIImageViewMultiborder.h" 22 | #import "RSUIImageViewMultiborder+PropertyHandler.h" 23 | #import "RSCotentModeHandler.h" 24 | 25 | 26 | @implementation RSUIImageViewMultiborder 27 | @synthesize isRounded = _isRounded; 28 | 29 | - (void)layoutSubviews 30 | { 31 | [super layoutSubviews]; 32 | 33 | /** 34 | * This code segment may confuse you but here is the explanation. We 35 | * set the isRounded property before the view is properly layoutted. 36 | * so settings it's corner radius before-hand layout sets it wrong 37 | * value. so after a layout is done we re-apply the isRounded 38 | * value, so that proper corner radius is set. 39 | */ 40 | self.isRounded = _isRounded; 41 | } 42 | 43 | // Only override drawRect: if you perform custom drawing. 44 | // An empty implementation adversely affects performance during animation. 45 | - (void)drawRect:(CGRect)rect { 46 | // Drawing code 47 | 48 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 49 | 50 | // drawing image 51 | [self handleImageDrawing]; 52 | 53 | // drawing border 54 | [self handleBorderDrawing:ctx]; 55 | } 56 | 57 | #pragma mark setMethod 58 | - (BOOL)isRounded 59 | { 60 | return self.isRounded; 61 | } 62 | - (void)setIsRounded:(BOOL)isRounded 63 | { 64 | _isRounded = isRounded; 65 | if(_isRounded) 66 | { 67 | self.layer.cornerRadius = CGRectGetMidX(self.bounds); 68 | self.clipsToBounds = YES; 69 | } 70 | else 71 | { 72 | self.layer.cornerRadius = 0.0; 73 | } 74 | } 75 | 76 | #pragma mark drawing related methods 77 | /** 78 | * This method manage all image drawing related task. 79 | * It actually generate the image according to the 80 | * self.contentMode, then draw the image according to 81 | * the inset created by the border. 82 | */ 83 | - (void)handleImageDrawing 84 | { 85 | CGFloat imageInset = 0; 86 | for(unsigned int index=0;index < [self.class getBorderCount]; index++) 87 | { 88 | imageInset += [self getBorderWidthAtIndex:index]; 89 | } 90 | 91 | // 92 | // get image based on contentMode 93 | // 94 | CGRect imageRect = CGRectInset(self.bounds, 95 | imageInset, 96 | imageInset); 97 | 98 | 99 | UIImage *resizedImage = [RSCotentModeHandler getImageForUIImage:self.image 100 | contentMode:self.contentMode 101 | forRect:CGRectMake(0, 102 | 0, 103 | CGRectGetWidth(imageRect), 104 | CGRectGetHeight(imageRect))]; 105 | [resizedImage drawInRect:imageRect]; 106 | } 107 | /** 108 | * This method manage all the border drawing related task. 109 | * It actually set the current stroke color according to the 110 | * currently drawing border, calculate the rect where the 111 | * border will be drawn and then draw the border by taking the 112 | * consideration of property "isRounded". An elipse is been drawn on 113 | * rounded case and an rect is drawn on non-rounded case. 114 | */ 115 | - (void)handleBorderDrawing:(CGContextRef)ctx 116 | { 117 | CGFloat summedBorderWidth = 0, currentBorderWidth; 118 | 119 | for(unsigned int index = 0; index < [self.class getBorderCount]; index++) 120 | { 121 | currentBorderWidth = [self getBorderWidthAtIndex:index]; 122 | 123 | if(!currentBorderWidth) continue;//if border is equal to zero, just ignore the drawing 124 | 125 | CGFloat size = summedBorderWidth + currentBorderWidth /2.0; 126 | 127 | [self drawBorderInContext:ctx 128 | atIndex:index 129 | inRect:CGRectInset(self.bounds,size,size)]; 130 | 131 | summedBorderWidth += currentBorderWidth; 132 | } 133 | } 134 | 135 | /** 136 | * This is the actual method which actually draws 137 | * each line, given the following parameters 138 | * 139 | * @param 140 | * ctx - CGContextRef of the current view drawing 141 | * index - NSUIteger index of the border, which is about to drawn 142 | * rect - CGRect, where the ellipse or rectagnle is about to be drawn 143 | * according to the isRounded property 144 | */ 145 | - (void)drawBorderInContext:(CGContextRef)ctx 146 | atIndex:(unsigned int)index 147 | inRect:(CGRect)rect 148 | { 149 | CGContextSetStrokeColorWithColor(ctx, [self getBorderColorAtIndex:index].CGColor); 150 | CGContextSetLineWidth(ctx, [self getBorderWidthAtIndex:index]); 151 | 152 | if(_isRounded) 153 | CGContextAddEllipseInRect(ctx, rect); 154 | else 155 | CGContextAddRect(ctx, rect); 156 | 157 | // 158 | // upcoming feature 159 | // 160 | // CGFloat ra[] = {2 , 2}; 161 | // CGContextSetLineDash(ctx, 0, ra, 2); 162 | // CGContextSetLineCap(ctx, kCGLineCapRound); 163 | CGContextStrokePath(ctx); 164 | } 165 | @end 166 | --------------------------------------------------------------------------------