Skip to content

Commit

Permalink
Convert to swift 5, add support for right-to-left input
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Prokop committed Oct 26, 2019
1 parent e777795 commit 7d2181c
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 54 deletions.
49 changes: 45 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ To add RatingView to your Storyboard/.xib file just drag a generic UIView from p

## Installation

### Carthage
- `cd` to your project folder
- `touch Cartfile` (if you don't have one yet)
- `nano Cartfile`
- put `github "peterprokop/StarryStars" == 2.0.0` into Cartfile
- Save it: `ctrl-x, y, enter`
- Run `carthage update`
- Copy framework from `Carthage/Build/iOS` to your project
- Make sure that framework is added in Embedded Binaries section of your target (or else you will get dyld library not loaded referenced from ... reason image not found error)
- Add `import StarryStars` on top of your view controller's code

### Manual
Just clone and add ```StarryStars``` directory to your project.

Expand All @@ -27,7 +38,7 @@ Just clone and add ```StarryStars``` directory to your project.
- `nano Podfile`, add:

```
pod 'StarryStars', '~> 0.0.1'
pod 'StarryStars', '~> 2.0.0'
use_frameworks!
```
- Save it: `ctrl-x`, `y`, `enter`
Expand All @@ -37,9 +48,39 @@ use_frameworks!

## Requirements

- iOS 8.0+
- Xcode 8.0+
- Swift 3.0 (for older versions, see `swift-2.2` branch)
- iOS 10.0+
- Xcode 10.0+
- Swift 5.0 (for older versions, see `swift-2.2` branch)

## Usage from code

Swift:
```
let rvRightToLeft = RatingView()
rvRightToLeft.frame = view.bounds
view.addSubview(rvRightToLeft)
rvRightToLeft.editable = true
rvRightToLeft.delegate = self
// RatingView will respect setting this property
rvRightToLeft.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
```

Objective C:
```
RatingView* rvRightToLeft = [[RatingView alloc] init];
rvRightToLeft.frame = self.view.bounds;
[self.view addSubview:rvRightToLeft];
rvRightToLeft.editable = YES;
rvRightToLeft.delegate = self;
// RatingView will respect setting this property
rvRightToLeft.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
```

## Other Projects

Expand Down
4 changes: 2 additions & 2 deletions StarryStars.podspec
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = 'StarryStars'
s.version = '1.0.0'
s.version = '2.0.0'
s.license = 'MIT'
s.summary = 'iOS GUI library for displaying and editing ratings'
s.homepage = 'https://github.com/peterprokop/StarryStars'
s.authors = { 'Peter Prokop' => '[email protected]' }
s.source = { :git => 'https://github.com/peterprokop/StarryStars.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.ios.deployment_target = '10.0'
s.requires_arc = 'true'
s.source_files = 'StarryStars/*.swift'
s.resources = [ "StarryStars/Resource/*.*" ]
Expand Down
72 changes: 49 additions & 23 deletions StarryStars/RatingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ open class RatingView: UIView {
@IBInspectable open var halfImage: UIImage?

/// Current rating, updates star images after setting
@IBInspectable open var rating: Float = Float(0) {
@IBInspectable open var rating: Float = 0 {
didSet {
// If rating is more than starCount simply set it to starCount
rating = min(Float(starCount), rating)
Expand All @@ -50,14 +50,23 @@ open class RatingView: UIView {

/// If set to "false" user will not be able to edit the rating
@IBInspectable open var editable: Bool = true



/// Delegate, must confrom to *RatingViewDelegate* protocol
open weak var delegate: RatingViewDelegate?

var stars = [UIImageView]()

@objc open weak var delegate: RatingViewDelegate?

var stars: [UIImageView] = []

override open var semanticContentAttribute: UISemanticContentAttribute {
didSet {
updateTransform()
}
}

private var shouldUseRightToLeft: Bool {
return UIView.userInterfaceLayoutDirection(for: semanticContentAttribute)
== .rightToLeft
}

override init(frame: CGRect) {
super.init(frame: frame)

Expand Down Expand Up @@ -109,28 +118,37 @@ open class RatingView: UIView {

layoutStars()
updateRating()

updateTransform()
}

override open func layoutSubviews() {
super.layoutSubviews()

layoutStars()
}

private func updateTransform() {
transform = shouldUseRightToLeft
? CGAffineTransform.init(scaleX: -1, y: 1)
: .identity
}

func layoutStars() {
if stars.count != 0,
let offImage = stars.first?.image {
let halfWidth = offImage.size.width/2
let distance = (bounds.size.width - (offImage.size.width * CGFloat(starCount))) / CGFloat(starCount + 1) + halfWidth

var i = 1
for iv in stars {
iv.frame = CGRect(x: 0, y: 0, width: offImage.size.width, height: offImage.size.height)

iv.center = CGPoint(x: CGFloat(i) * distance + halfWidth * CGFloat(i - 1),
y: self.frame.size.height/2)
i += 1
}
private func layoutStars() {
guard !stars.isEmpty, let offImage = stars.first?.image else {
return
}

let halfWidth = offImage.size.width/2
let distance = (bounds.size.width - (offImage.size.width * CGFloat(starCount))) / CGFloat(starCount + 1) + halfWidth

for (index, iv) in stars.enumerated() {
iv.frame = CGRect(x: 0, y: 0, width: offImage.size.width, height: offImage.size.height)

iv.center = CGPoint(
x: CGFloat(index + 1) * distance + halfWidth * CGFloat(index),
y: self.frame.size.height/2
)
}
}

Expand All @@ -140,7 +158,7 @@ open class RatingView: UIView {
func handleTouches(_ touches: Set<UITouch>) {
let touch = touches.first!
let touchLocation = touch.location(in: self)

var i = starCount - 1
while i >= 0 {
let imageView = stars[i]
Expand All @@ -166,7 +184,7 @@ open class RatingView: UIView {
*/
func updateRating() {
// To avoid crash when using IB
if stars.count == 0 {
guard !stars.isEmpty else {
return
}

Expand Down Expand Up @@ -217,3 +235,11 @@ extension RatingView {
delegate.ratingView(self, didChangeRating: rating)
}
}

@objc extension RatingView {
@objc public enum FillDirection: Int {
case automatic
case leftToRight
case rightToLeft
}
}
43 changes: 35 additions & 8 deletions StarryStarsExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
0D39D5D51E23CD450014489F /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = 0D98B9B51BE60BDB00D89929 /* [email protected] */; };
0D39D5D61E23CD480014489F /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = 0D98B9B61BE60BDB00D89929 /* [email protected] */; };
0D39D5D71E23CD4B0014489F /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = 0D98B9B71BE60BDB00D89929 /* [email protected] */; };
2FE9711B23648E62002212C5 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 2FE9711A23648E62002212C5 /* README.md */; };
2FE9711D23649023002212C5 /* StarryStars.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2FE9711C23649023002212C5 /* StarryStars.podspec */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -62,6 +64,8 @@
0D98B9B61BE60BDB00D89929 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
0D98B9B71BE60BDB00D89929 /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
0DEBD39B1BDA134D00FC7856 /* StarryStarsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StarryStarsExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
2FE9711A23648E62002212C5 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
2FE9711C23649023002212C5 /* StarryStars.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = StarryStars.podspec; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -122,6 +126,8 @@
0DEBD3921BDA134D00FC7856 = {
isa = PBXGroup;
children = (
2FE9711A23648E62002212C5 /* README.md */,
2FE9711C23649023002212C5 /* StarryStars.podspec */,
0D2DE71C1BE5F83C005DBFEC /* StarryStars */,
0D2DE7081BE5F23E005DBFEC /* StarryStarsExample */,
0DEBD39C1BDA134D00FC7856 /* Products */,
Expand Down Expand Up @@ -195,7 +201,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0820;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Peter Prokop";
TargetAttributes = {
0D39D5C61E23CD0F0014489F = {
Expand All @@ -210,7 +216,7 @@
};
buildConfigurationList = 0DEBD3961BDA134D00FC7856 /* Build configuration list for PBXProject "StarryStarsExample" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Expand Down Expand Up @@ -242,6 +248,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2FE9711B23648E62002212C5 /* README.md in Resources */,
2FE9711D23649023002212C5 /* StarryStars.podspec in Resources */,
0D2DE7161BE5F23E005DBFEC /* Main.storyboard in Resources */,
0D2DE7151BE5F23E005DBFEC /* LaunchScreen.storyboard in Resources */,
);
Expand Down Expand Up @@ -311,13 +319,13 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = StarryStars/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Prokop.StarryStars;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
Expand All @@ -337,12 +345,12 @@
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = StarryStars/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 10.2;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Prokop.StarryStars;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
Expand All @@ -357,14 +365,22 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
Expand Down Expand Up @@ -403,14 +419,22 @@
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
Expand Down Expand Up @@ -442,12 +466,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = StarryStarsExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Prokop.StarryStarsExample;
PRODUCT_NAME = StarryStarsExample;
SWIFT_OBJC_BRIDGING_HEADER = "StarryStarsExample/StarryStarsExample-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
Expand All @@ -458,11 +483,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = StarryStarsExample/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = Prokop.StarryStarsExample;
PRODUCT_NAME = StarryStarsExample;
SWIFT_OBJC_BRIDGING_HEADER = "StarryStarsExample/StarryStarsExample-Bridging-Header.h";
SWIFT_VERSION = 3.0;
SWIFT_VERSION = 5.0;
};
name = Release;
};
Expand All @@ -476,6 +502,7 @@
0D39D5D11E23CD0F0014489F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0DEBD3961BDA134D00FC7856 /* Build configuration list for PBXProject "StarryStarsExample" */ = {
isa = XCConfigurationList;
Expand Down
4 changes: 1 addition & 3 deletions StarryStarsExample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
Expand All @@ -40,6 +39,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


}

Loading

0 comments on commit 7d2181c

Please sign in to comment.