Skip to content

Instantly share code, notes, and snippets.

@matsuda
Last active October 14, 2017 06:44
Show Gist options
  • Save matsuda/3f05ae576a1f1b4058284f4d267f4457 to your computer and use it in GitHub Desktop.
Save matsuda/3f05ae576a1f1b4058284f4d267f4457 to your computer and use it in GitHub Desktop.
///
/// MARK: - BadgeButton
///
class BadgeButton: UIButton {
let badgeLabel: BadgeLabel = BadgeLabel()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
convenience init(badge: String?) {
self.init(frame: .zero)
initialize()
badgeLabel.text = badge
}
private func initialize() {
addSubview(badgeLabel)
badgeLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: badgeLabel, attribute: .centerX, relatedBy: .equal,
toItem: self, attribute: .centerX,
multiplier: 1, constant: 6).isActive = true
NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal,
toItem: badgeLabel, attribute: .centerY,
multiplier: 1, constant: 6).isActive = true
}
}
///
/// MARK: - BadgeLabel
///
class BadgeLabel: UILabel {
var badgeColor: UIColor = UIColor.red
override var text: String? {
didSet {
guard let text = self.text else {
isHidden = true
return
}
if text.isEmpty {
isHidden = true
return
}
if let count = Int(text), count == 0 {
isHidden = true
return
}
isHidden = false
}
}
override init(frame: CGRect) {
super.init(frame: frame)
initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialize()
}
init(badge: String?, color: UIColor = .red) {
self.init()
initialize()
badgeColor = color
text = badge
}
private func initialize() {
textColor = UIColor.white
backgroundColor = UIColor.clear
textAlignment = .center
}
private let minimumSize: CGSize = CGSize(width: 16, height: 16)
private let margin: CGFloat = 1
override func draw(_ rect: CGRect) {
badgeColor.setFill()
let path = UIBezierPath()
let unit = rect.height / 2
var point = CGPoint(x: rect.minX + unit, y: rect.minY)
path.move(to: point)
point.x = rect.maxX - unit
path.addLine(to: point)
point.y = rect.midY
path.addArc(withCenter: point, radius: unit,
startAngle: CGFloat(-M_PI / 2),
endAngle: CGFloat(M_PI / 2),
clockwise: true)
point.y = rect.maxY
point.x = rect.minX + unit
path.addLine(to: point)
point.y = rect.midY
path.addArc(withCenter: point, radius: unit,
startAngle: CGFloat(M_PI / 2),
endAngle: CGFloat(-M_PI / 2),
clockwise: true)
path.close()
path.fill()
super.draw(rect)
}
/*
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin)
let rect = UIEdgeInsetsInsetRect(rect, insets)
super.drawText(in: rect)
}
*/
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
if size.height < minimumSize.height {
size.height = minimumSize.height
}
size.width += margin * 2
size.height += margin * 2
if size.width < size.height {
size.width = size.height
}
return size
}
}
///
/// MARK: - BadgeBarButtonItem
///
class BadgeBarButtonItem: UIBarButtonItem {
private var badgeButton: BadgeButton {
return customView as! BadgeButton
}
var badgeLabel: BadgeLabel {
return badgeButton.badgeLabel
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("Not supported \(#function).")
}
init(badge: String?, target: Any?, action: Selector) {
let button = BadgeButton(badge: badge)
button.isExclusiveTouch = true
button.setImage(UIImage(named: "btn_badge"), for: .normal)
button.addTarget(target, action: action, for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 45, height: 30)
super.init()
customView = button
addObserve()
}
deinit {
removeObserve()
}
private func addObserve() {
NotificationCenter.default.addObserver(self, selector: #selector(didChangeBadgeCount(notification:)), name: Notification.Name("DidChangeBadgeCount"), object: nil)
}
private func removeObserve() {
NotificationCenter.default.removeObserver(self, name: Notification.Name("DidChangeBadgeCount"), object: nil)
}
func didChangeBadgeCount(notification: Notification) {
guard let userInfo = notification.userInfo,
let count = userInfo["BadgeCount"] as? Int else {
return
}
badgeLabel.text = BadgeBarButtonItem.badgeCountText(count: count)
}
class func badgeCountText(count: Int) -> String {
if count > 30 {
return "30+"
} else {
return String(count)
}
}
}
// MARK: - app version
func appVersion() -> String {
return Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
}
// MARK: - NSBundle
func bundlePath(path: String) -> String? {
let resourcePath = Bundle.main.resourcePath as NSString?
return resourcePath?.appendingPathComponent(path)
}
// MARK: - app launguage
func currentLaunguage() -> String {
if let languageAndCountry = Locale.preferredLanguages.first,
let language = languageAndCountry.components(separatedBy: "-").first
{
return language
}
return "en"
}
// MARK: - localize wrapper
func AppLocalizedStringFromTable(key: String, tableName: String? = nil, comment: String) -> String {
guard
let path = Bundle.main.path(forResource: currentLaunguage(), ofType: "lproj"),
let bundle = Bundle(path: path),
let tableName = tableName else {
return NSLocalizedString(key, comment: comment)
}
return bundle.localizedString(forKey: key, value: nil, table: tableName)
// return NSLocalizedString(key, tableName: tableName, bundle: bundle, comment: comment)
}
/*
enumに適用することを想定
enum以外では未確認
*/
///
/// MARK: - ResourceBundle
///
protocol ResourceBundle {
associatedtype T
static var bundleName: String { get }
static func value(forKey key: String) -> T
func value(forKey key: String) -> T
}
extension ResourceBundle {
static func value(forKey key: String) -> T {
let path = bundlePath()!
let dict = NSDictionary(contentsOfFile: path)!
return dict[key] as! T
}
func value(forKey key: String) -> T {
return type(of: self).value(forKey: key)
}
static func bundlePath() -> String? {
guard let path = Bundle.main.path(forResource: bundleName, ofType: "bundle") else { return nil }
return Bundle(path: path)?.path(forResource: "\(self)", ofType: "plist")
// return NSBundle.resourceBundle(bundleName)?.pathForResourcePlist("\(self)")
// return bundle().pathForResource("\(self)", ofType: "plist")
}
/*
static func bundle() -> NSBundle {
let path = NSBundle.mainBundle().pathForResource(bundleName, ofType: "bundle")!
return NSBundle(path: path)!
}
*/
}
///
/// MARK: - RawStringEnumerable
///
/// @see RawRepresentable
///
protocol RawStringEnumerable {
var rawValue: String { get }
init?(rawValue: String)
}
extension ResourceBundle where Self: RawStringEnumerable {
var value: T {
return value(forKey: rawValue)
}
}
// example
//
// MARK: - MyServiceResource
//
protocol MyServiceResourceBundle: ResourceBundle {}
extension MyServiceResourceBundle {
static var bundleName: String {
return "MyService"
}
}
//
// MARK: - Resource
//
struct Resource {}
extension Resource {
enum URLs: String, MyServiceResourceBundle, RawStringEnumerable {
typealias T = String
case login
/*
#if DEBUG || ADHOC
static func value(forKey key: String) -> String {
let path = bundlePath()!
let dict = NSDictionary(contentsOfFile: path)!
let value = dict[key] as! T
let pattern = "(https?://)([^/]+?)(/.*)"
let scheme = Network.sharedNetwork.URL.scheme!
let host = Network.sharedNetwork.URL.host!
var hostWithPort: String!
if let port = Network.sharedNetwork.URL.port {
// hostWithPort = "$1\(host):\(port)$3"
hostWithPort = "\(scheme)://\(host):\(port)$3"
} else {
// hostWithPort = "$1\(host)$3"
hostWithPort = "\(scheme)://\(host)$3"
}
let str = value.replacingOccurrences(
of: pattern,
with: hostWithPort,
options: [.regularExpression],
range: nil
)
return str
}
#endif
*/
}
}
// alias
typealias R = Resource
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment