├── .gitignore
├── .travis.yml
├── Example
├── Podfile
├── Podfile.lock
├── Pods
│ ├── Local Podspecs
│ │ └── RJBadgeKit.podspec.json
│ ├── Manifest.lock
│ ├── Pods.xcodeproj
│ │ └── project.pbxproj
│ └── Target Support Files
│ │ ├── Pods-RJBadgeKit_Example
│ │ ├── Info.plist
│ │ ├── Pods-RJBadgeKit_Example-acknowledgements.markdown
│ │ ├── Pods-RJBadgeKit_Example-acknowledgements.plist
│ │ ├── Pods-RJBadgeKit_Example-dummy.m
│ │ ├── Pods-RJBadgeKit_Example-frameworks.sh
│ │ ├── Pods-RJBadgeKit_Example-resources.sh
│ │ ├── Pods-RJBadgeKit_Example-umbrella.h
│ │ ├── Pods-RJBadgeKit_Example.debug.xcconfig
│ │ ├── Pods-RJBadgeKit_Example.modulemap
│ │ └── Pods-RJBadgeKit_Example.release.xcconfig
│ │ ├── Pods-RJBadgeKit_Tests
│ │ ├── Info.plist
│ │ ├── Pods-RJBadgeKit_Tests-acknowledgements.markdown
│ │ ├── Pods-RJBadgeKit_Tests-acknowledgements.plist
│ │ ├── Pods-RJBadgeKit_Tests-dummy.m
│ │ ├── Pods-RJBadgeKit_Tests-frameworks.sh
│ │ ├── Pods-RJBadgeKit_Tests-resources.sh
│ │ ├── Pods-RJBadgeKit_Tests-umbrella.h
│ │ ├── Pods-RJBadgeKit_Tests.debug.xcconfig
│ │ ├── Pods-RJBadgeKit_Tests.modulemap
│ │ └── Pods-RJBadgeKit_Tests.release.xcconfig
│ │ └── RJBadgeKit
│ │ ├── Info.plist
│ │ ├── RJBadgeKit-dummy.m
│ │ ├── RJBadgeKit-prefix.pch
│ │ ├── RJBadgeKit-umbrella.h
│ │ ├── RJBadgeKit.modulemap
│ │ └── RJBadgeKit.xcconfig
├── RJBadgeKit.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── RJBadgeKit-Example.xcscheme
├── RJBadgeKit.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── RJBadgeKit
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Images.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── badgeNew.imageset
│ │ │ ├── Contents.json
│ │ │ ├── badgeNew@2x.png
│ │ │ └── badgeNew@3x.png
│ ├── RJAppDelegate.h
│ ├── RJAppDelegate.m
│ ├── RJBadgeKit-Info.plist
│ ├── RJBadgeKit-Prefix.pch
│ ├── RJDemoViewController.h
│ ├── RJDemoViewController.m
│ ├── RJDetailViewController.h
│ ├── RJDetailViewController.m
│ ├── RJViewController.h
│ ├── RJViewController.m
│ ├── en.lproj
│ │ └── InfoPlist.strings
│ └── main.m
├── Tests
│ ├── Tests-Info.plist
│ ├── Tests-Prefix.pch
│ ├── Tests.m
│ └── en.lproj
│ │ └── InfoPlist.strings
├── demo.gif
└── path.png
├── LICENSE
├── README.md
├── RJBadgeKit.podspec
├── RJBadgeKit
├── Assets
│ └── .gitkeep
└── Classes
│ ├── .gitkeep
│ ├── BadgeController
│ ├── NSObject+RJBadgeController.h
│ ├── NSObject+RJBadgeController.m
│ ├── RJBadgeController.h
│ ├── RJBadgeController.m
│ ├── RJBadgeManager.h
│ └── RJBadgeManager.m
│ ├── BadgeModel
│ ├── RJBadge.h
│ ├── RJBadgeInfo.h
│ ├── RJBadgeInfo.m
│ ├── RJBadgeModel.h
│ └── RJBadgeModel.m
│ ├── BadgeView
│ ├── RJBadgeView.h
│ ├── UIBarButtonItem+RJBadge.h
│ ├── UIBarButtonItem+RJBadge.m
│ ├── UITabBarItem+RJBadge.h
│ ├── UITabBarItem+RJBadge.m
│ ├── UIView+RJBadge.h
│ └── UIView+RJBadge.m
│ ├── Helper
│ ├── NSString+RJBadge.h
│ └── NSString+RJBadge.m
│ └── RJBadgeKit.h
└── _Pods.xcodeproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | Carthage
26 | # We recommend against adding the Pods directory to your .gitignore. However
27 | # you should judge for yourself, the pros and cons are mentioned at:
28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29 | #
30 | # Note: if you ignore the Pods directory, make sure to uncomment
31 | # `pod install` in .travis.yml
32 | #
33 | # Pods/
34 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * http://www.objc.io/issue-6/travis-ci.html
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | osx_image: xcode7.3
6 | language: objective-c
7 | # cache: cocoapods
8 | # podfile: Example/Podfile
9 | # before_install:
10 | # - gem install cocoapods # Since Travis is not always on latest version
11 | # - pod install --project-directory=Example
12 | script:
13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/RJBadgeKit.xcworkspace -scheme RJBadgeKit-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
14 | - pod lib lint
15 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | use_frameworks!
2 |
3 | target 'RJBadgeKit_Example' do
4 | pod 'RJBadgeKit', :path => '../'
5 |
6 | target 'RJBadgeKit_Tests' do
7 | inherit! :search_paths
8 |
9 |
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - RJBadgeKit (0.2.1)
3 |
4 | DEPENDENCIES:
5 | - RJBadgeKit (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | RJBadgeKit:
9 | :path: ../
10 |
11 | SPEC CHECKSUMS:
12 | RJBadgeKit: db6f8f09f92f92e2473142aa4fee46121de6d716
13 |
14 | PODFILE CHECKSUM: 2fb6b623b87aeb174cd13a4c34101b548b391a79
15 |
16 | COCOAPODS: 1.3.1
17 |
--------------------------------------------------------------------------------
/Example/Pods/Local Podspecs/RJBadgeKit.podspec.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RJBadgeKit",
3 | "version": "0.2.1",
4 | "summary": "Red dot (version/message reminder) display and its management.",
5 | "description": "A complete and lightweight solution for red dot (version/message reminder) display and its management.",
6 | "homepage": "https://github.com/RylanJIN/RJBadgeKit",
7 | "license": {
8 | "type": "MIT",
9 | "file": "LICENSE"
10 | },
11 | "authors": {
12 | "Ryan Jin": "xiaojun.jin@outlook.com"
13 | },
14 | "source": {
15 | "git": "https://github.com/RylanJIN/RJBadgeKit.git",
16 | "tag": "0.2.1"
17 | },
18 | "platforms": {
19 | "ios": "8.0"
20 | },
21 | "source_files": "RJBadgeKit/Classes/**/*"
22 | }
23 |
--------------------------------------------------------------------------------
/Example/Pods/Manifest.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - RJBadgeKit (0.2.1)
3 |
4 | DEPENDENCIES:
5 | - RJBadgeKit (from `../`)
6 |
7 | EXTERNAL SOURCES:
8 | RJBadgeKit:
9 | :path: ../
10 |
11 | SPEC CHECKSUMS:
12 | RJBadgeKit: db6f8f09f92f92e2473142aa4fee46121de6d716
13 |
14 | PODFILE CHECKSUM: 2fb6b623b87aeb174cd13a4c34101b548b391a79
15 |
16 | COCOAPODS: 1.3.1
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_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 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 |
4 | ## RJBadgeKit
5 |
6 | Copyright (c) 2017 RylanJIN
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in
16 | all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | THE SOFTWARE.
25 |
26 | Generated by CocoaPods - https://cocoapods.org
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Copyright (c) 2017 RylanJIN <xiaojun.jin@outlook.com>
18 |
19 | Permission is hereby granted, free of charge, to any person obtaining a copy
20 | of this software and associated documentation files (the "Software"), to deal
21 | in the Software without restriction, including without limitation the rights
22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23 | copies of the Software, and to permit persons to whom the Software is
24 | furnished to do so, subject to the following conditions:
25 |
26 | The above copyright notice and this permission notice shall be included in
27 | all copies or substantial portions of the Software.
28 |
29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35 | THE SOFTWARE.
36 |
37 | License
38 | MIT
39 | Title
40 | RJBadgeKit
41 | Type
42 | PSGroupSpecifier
43 |
44 |
45 | FooterText
46 | Generated by CocoaPods - https://cocoapods.org
47 | Title
48 |
49 | Type
50 | PSGroupSpecifier
51 |
52 |
53 | StringsTable
54 | Acknowledgements
55 | Title
56 | Acknowledgements
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_RJBadgeKit_Example : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_RJBadgeKit_Example
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
12 |
13 | install_framework()
14 | {
15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
16 | local source="${BUILT_PRODUCTS_DIR}/$1"
17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
19 | elif [ -r "$1" ]; then
20 | local source="$1"
21 | fi
22 |
23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
24 |
25 | if [ -L "${source}" ]; then
26 | echo "Symlinked..."
27 | source="$(readlink "${source}")"
28 | fi
29 |
30 | # Use filter instead of exclude so missing patterns don't throw errors.
31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
33 |
34 | local basename
35 | basename="$(basename -s .framework "$1")"
36 | binary="${destination}/${basename}.framework/${basename}"
37 | if ! [ -r "$binary" ]; then
38 | binary="${destination}/${basename}"
39 | fi
40 |
41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
43 | strip_invalid_archs "$binary"
44 | fi
45 |
46 | # Resign the code if required by the build settings to avoid unstable apps
47 | code_sign_if_enabled "${destination}/$(basename "$1")"
48 |
49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
51 | local swift_runtime_libs
52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
53 | for lib in $swift_runtime_libs; do
54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
56 | code_sign_if_enabled "${destination}/${lib}"
57 | done
58 | fi
59 | }
60 |
61 | # Copies the dSYM of a vendored framework
62 | install_dsym() {
63 | local source="$1"
64 | if [ -r "$source" ]; then
65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
67 | fi
68 | }
69 |
70 | # Signs a framework with the provided identity
71 | code_sign_if_enabled() {
72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
73 | # Use the current code_sign_identitiy
74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
76 |
77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
78 | code_sign_cmd="$code_sign_cmd &"
79 | fi
80 | echo "$code_sign_cmd"
81 | eval "$code_sign_cmd"
82 | fi
83 | }
84 |
85 | # Strip invalid architectures
86 | strip_invalid_archs() {
87 | binary="$1"
88 | # Get architectures for current file
89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
90 | stripped=""
91 | for arch in $archs; do
92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
93 | # Strip non-valid architectures in-place
94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
95 | stripped="$stripped $arch"
96 | fi
97 | done
98 | if [[ "$stripped" ]]; then
99 | echo "Stripped $binary of architectures:$stripped"
100 | fi
101 | }
102 |
103 |
104 | if [[ "$CONFIGURATION" == "Debug" ]]; then
105 | install_framework "${BUILT_PRODUCTS_DIR}/RJBadgeKit/RJBadgeKit.framework"
106 | fi
107 | if [[ "$CONFIGURATION" == "Release" ]]; then
108 | install_framework "${BUILT_PRODUCTS_DIR}/RJBadgeKit/RJBadgeKit.framework"
109 | fi
110 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
111 | wait
112 | fi
113 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
14 |
15 | case "${TARGETED_DEVICE_FAMILY}" in
16 | 1,2)
17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
18 | ;;
19 | 1)
20 | TARGET_DEVICE_ARGS="--target-device iphone"
21 | ;;
22 | 2)
23 | TARGET_DEVICE_ARGS="--target-device ipad"
24 | ;;
25 | 3)
26 | TARGET_DEVICE_ARGS="--target-device tv"
27 | ;;
28 | 4)
29 | TARGET_DEVICE_ARGS="--target-device watch"
30 | ;;
31 | *)
32 | TARGET_DEVICE_ARGS="--target-device mac"
33 | ;;
34 | esac
35 |
36 | install_resource()
37 | {
38 | if [[ "$1" = /* ]] ; then
39 | RESOURCE_PATH="$1"
40 | else
41 | RESOURCE_PATH="${PODS_ROOT}/$1"
42 | fi
43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
44 | cat << EOM
45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
46 | EOM
47 | exit 1
48 | fi
49 | case $RESOURCE_PATH in
50 | *.storyboard)
51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
53 | ;;
54 | *.xib)
55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
57 | ;;
58 | *.framework)
59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
63 | ;;
64 | *.xcdatamodel)
65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
67 | ;;
68 | *.xcdatamodeld)
69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
71 | ;;
72 | *.xcmappingmodel)
73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
75 | ;;
76 | *.xcassets)
77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
79 | ;;
80 | *)
81 | echo "$RESOURCE_PATH" || true
82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
83 | ;;
84 | esac
85 | }
86 |
87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
92 | fi
93 | rm -f "$RESOURCES_TO_COPY"
94 |
95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
96 | then
97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
99 | while read line; do
100 | if [[ $line != "${PODS_ROOT}*" ]]; then
101 | XCASSET_FILES+=("$line")
102 | fi
103 | done <<<"$OTHER_XCASSETS"
104 |
105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
106 | fi
107 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_RJBadgeKit_ExampleVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_RJBadgeKit_ExampleVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example.debug.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit/RJBadgeKit.framework/Headers"
5 | OTHER_LDFLAGS = $(inherited) -framework "RJBadgeKit"
6 | PODS_BUILD_DIR = $BUILD_DIR
7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_RJBadgeKit_Example {
2 | umbrella header "Pods-RJBadgeKit_Example-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example.release.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit/RJBadgeKit.framework/Headers"
5 | OTHER_LDFLAGS = $(inherited) -framework "RJBadgeKit"
6 | PODS_BUILD_DIR = $BUILD_DIR
7 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
8 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
9 | PODS_ROOT = ${SRCROOT}/Pods
10 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | ${PRODUCT_BUNDLE_IDENTIFIER}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-acknowledgements.markdown:
--------------------------------------------------------------------------------
1 | # Acknowledgements
2 | This application makes use of the following third party libraries:
3 | Generated by CocoaPods - https://cocoapods.org
4 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-acknowledgements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 | FooterText
9 | This application makes use of the following third party libraries:
10 | Title
11 | Acknowledgements
12 | Type
13 | PSGroupSpecifier
14 |
15 |
16 | FooterText
17 | Generated by CocoaPods - https://cocoapods.org
18 | Title
19 |
20 | Type
21 | PSGroupSpecifier
22 |
23 |
24 | StringsTable
25 | Acknowledgements
26 | Title
27 | Acknowledgements
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_Pods_RJBadgeKit_Tests : NSObject
3 | @end
4 | @implementation PodsDummy_Pods_RJBadgeKit_Tests
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-frameworks.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
6 |
7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
8 |
9 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
10 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
11 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
12 |
13 | install_framework()
14 | {
15 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
16 | local source="${BUILT_PRODUCTS_DIR}/$1"
17 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
18 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
19 | elif [ -r "$1" ]; then
20 | local source="$1"
21 | fi
22 |
23 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
24 |
25 | if [ -L "${source}" ]; then
26 | echo "Symlinked..."
27 | source="$(readlink "${source}")"
28 | fi
29 |
30 | # Use filter instead of exclude so missing patterns don't throw errors.
31 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
32 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
33 |
34 | local basename
35 | basename="$(basename -s .framework "$1")"
36 | binary="${destination}/${basename}.framework/${basename}"
37 | if ! [ -r "$binary" ]; then
38 | binary="${destination}/${basename}"
39 | fi
40 |
41 | # Strip invalid architectures so "fat" simulator / device frameworks work on device
42 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
43 | strip_invalid_archs "$binary"
44 | fi
45 |
46 | # Resign the code if required by the build settings to avoid unstable apps
47 | code_sign_if_enabled "${destination}/$(basename "$1")"
48 |
49 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
50 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
51 | local swift_runtime_libs
52 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]})
53 | for lib in $swift_runtime_libs; do
54 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
55 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
56 | code_sign_if_enabled "${destination}/${lib}"
57 | done
58 | fi
59 | }
60 |
61 | # Copies the dSYM of a vendored framework
62 | install_dsym() {
63 | local source="$1"
64 | if [ -r "$source" ]; then
65 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\""
66 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}"
67 | fi
68 | }
69 |
70 | # Signs a framework with the provided identity
71 | code_sign_if_enabled() {
72 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
73 | # Use the current code_sign_identitiy
74 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
75 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
76 |
77 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
78 | code_sign_cmd="$code_sign_cmd &"
79 | fi
80 | echo "$code_sign_cmd"
81 | eval "$code_sign_cmd"
82 | fi
83 | }
84 |
85 | # Strip invalid architectures
86 | strip_invalid_archs() {
87 | binary="$1"
88 | # Get architectures for current file
89 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
90 | stripped=""
91 | for arch in $archs; do
92 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then
93 | # Strip non-valid architectures in-place
94 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1
95 | stripped="$stripped $arch"
96 | fi
97 | done
98 | if [[ "$stripped" ]]; then
99 | echo "Stripped $binary of architectures:$stripped"
100 | fi
101 | }
102 |
103 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
104 | wait
105 | fi
106 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-resources.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
5 |
6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
7 | > "$RESOURCES_TO_COPY"
8 |
9 | XCASSET_FILES=()
10 |
11 | # This protects against multiple targets copying the same framework dependency at the same time. The solution
12 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html
13 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????")
14 |
15 | case "${TARGETED_DEVICE_FAMILY}" in
16 | 1,2)
17 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
18 | ;;
19 | 1)
20 | TARGET_DEVICE_ARGS="--target-device iphone"
21 | ;;
22 | 2)
23 | TARGET_DEVICE_ARGS="--target-device ipad"
24 | ;;
25 | 3)
26 | TARGET_DEVICE_ARGS="--target-device tv"
27 | ;;
28 | 4)
29 | TARGET_DEVICE_ARGS="--target-device watch"
30 | ;;
31 | *)
32 | TARGET_DEVICE_ARGS="--target-device mac"
33 | ;;
34 | esac
35 |
36 | install_resource()
37 | {
38 | if [[ "$1" = /* ]] ; then
39 | RESOURCE_PATH="$1"
40 | else
41 | RESOURCE_PATH="${PODS_ROOT}/$1"
42 | fi
43 | if [[ ! -e "$RESOURCE_PATH" ]] ; then
44 | cat << EOM
45 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
46 | EOM
47 | exit 1
48 | fi
49 | case $RESOURCE_PATH in
50 | *.storyboard)
51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
53 | ;;
54 | *.xib)
55 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true
56 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
57 | ;;
58 | *.framework)
59 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
60 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
61 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true
62 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
63 | ;;
64 | *.xcdatamodel)
65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true
66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
67 | ;;
68 | *.xcdatamodeld)
69 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true
70 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
71 | ;;
72 | *.xcmappingmodel)
73 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true
74 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
75 | ;;
76 | *.xcassets)
77 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
78 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
79 | ;;
80 | *)
81 | echo "$RESOURCE_PATH" || true
82 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
83 | ;;
84 | esac
85 | }
86 |
87 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
88 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
89 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
90 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
91 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
92 | fi
93 | rm -f "$RESOURCES_TO_COPY"
94 |
95 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
96 | then
97 | # Find all other xcassets (this unfortunately includes those of path pods and other targets).
98 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
99 | while read line; do
100 | if [[ $line != "${PODS_ROOT}*" ]]; then
101 | XCASSET_FILES+=("$line")
102 | fi
103 | done <<<"$OTHER_XCASSETS"
104 |
105 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
106 | fi
107 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
14 | FOUNDATION_EXPORT double Pods_RJBadgeKit_TestsVersionNumber;
15 | FOUNDATION_EXPORT const unsigned char Pods_RJBadgeKit_TestsVersionString[];
16 |
17 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests.debug.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit/RJBadgeKit.framework/Headers"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests.modulemap:
--------------------------------------------------------------------------------
1 | framework module Pods_RJBadgeKit_Tests {
2 | umbrella header "Pods-RJBadgeKit_Tests-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests.release.xcconfig:
--------------------------------------------------------------------------------
1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit"
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
4 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit/RJBadgeKit.framework/Headers"
5 | PODS_BUILD_DIR = $BUILD_DIR
6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
8 | PODS_ROOT = ${SRCROOT}/Pods
9 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/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 | FMWK
17 | CFBundleShortVersionString
18 | 0.2.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | ${CURRENT_PROJECT_VERSION}
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/RJBadgeKit-dummy.m:
--------------------------------------------------------------------------------
1 | #import
2 | @interface PodsDummy_RJBadgeKit : NSObject
3 | @end
4 | @implementation PodsDummy_RJBadgeKit
5 | @end
6 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/RJBadgeKit-prefix.pch:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/RJBadgeKit-umbrella.h:
--------------------------------------------------------------------------------
1 | #ifdef __OBJC__
2 | #import
3 | #else
4 | #ifndef FOUNDATION_EXPORT
5 | #if defined(__cplusplus)
6 | #define FOUNDATION_EXPORT extern "C"
7 | #else
8 | #define FOUNDATION_EXPORT extern
9 | #endif
10 | #endif
11 | #endif
12 |
13 | #import "NSObject+RJBadgeController.h"
14 | #import "RJBadgeController.h"
15 | #import "RJBadgeManager.h"
16 | #import "RJBadge.h"
17 | #import "RJBadgeInfo.h"
18 | #import "RJBadgeModel.h"
19 | #import "RJBadgeView.h"
20 | #import "UIBarButtonItem+RJBadge.h"
21 | #import "UITabBarItem+RJBadge.h"
22 | #import "UIView+RJBadge.h"
23 | #import "NSString+RJBadge.h"
24 | #import "RJBadgeKit.h"
25 |
26 | FOUNDATION_EXPORT double RJBadgeKitVersionNumber;
27 | FOUNDATION_EXPORT const unsigned char RJBadgeKitVersionString[];
28 |
29 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/RJBadgeKit.modulemap:
--------------------------------------------------------------------------------
1 | framework module RJBadgeKit {
2 | umbrella header "RJBadgeKit-umbrella.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/Example/Pods/Target Support Files/RJBadgeKit/RJBadgeKit.xcconfig:
--------------------------------------------------------------------------------
1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/RJBadgeKit
2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public"
4 | PODS_BUILD_DIR = $BUILD_DIR
5 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
6 | PODS_ROOT = ${SRCROOT}
7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../..
8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
9 | SKIP_INSTALL = YES
10 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0DD0F3191BF43C6EF9F153DD /* Pods_RJBadgeKit_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 637DF2DA6661A379648E30F1 /* Pods_RJBadgeKit_Example.framework */; };
11 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
12 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
13 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
14 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
15 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; };
16 | 6003F59E195388D20070C39A /* RJAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* RJAppDelegate.m */; };
17 | 6003F5A7195388D20070C39A /* RJViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* RJViewController.m */; };
18 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; };
19 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
20 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
21 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
22 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
23 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; };
24 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; };
25 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
26 | 94DE14D41FECDD4B00A7FCB3 /* RJDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94DE14D31FECDD4B00A7FCB3 /* RJDemoViewController.m */; };
27 | 94DE14D71FECDD5C00A7FCB3 /* RJDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 94DE14D61FECDD5C00A7FCB3 /* RJDetailViewController.m */; };
28 | E306F03EF3AB5DBDF40E4F5B /* Pods_RJBadgeKit_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03485BE7FF6C3D929E410387 /* Pods_RJBadgeKit_Tests.framework */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 6003F582195388D10070C39A /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 6003F589195388D20070C39A;
37 | remoteInfo = RJBadgeKit;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXFileReference section */
42 | 03485BE7FF6C3D929E410387 /* Pods_RJBadgeKit_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RJBadgeKit_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
43 | 26DDFFA3B26F1ABE8A296A1F /* Pods-RJBadgeKit_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RJBadgeKit_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests.release.xcconfig"; sourceTree = ""; };
44 | 6003F58A195388D20070C39A /* RJBadgeKit_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RJBadgeKit_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
45 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
46 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
47 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
48 | 6003F595195388D20070C39A /* RJBadgeKit-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RJBadgeKit-Info.plist"; sourceTree = ""; };
49 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
50 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
51 | 6003F59B195388D20070C39A /* RJBadgeKit-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RJBadgeKit-Prefix.pch"; sourceTree = ""; };
52 | 6003F59C195388D20070C39A /* RJAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RJAppDelegate.h; sourceTree = ""; };
53 | 6003F59D195388D20070C39A /* RJAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RJAppDelegate.m; sourceTree = ""; };
54 | 6003F5A5195388D20070C39A /* RJViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RJViewController.h; sourceTree = ""; };
55 | 6003F5A6195388D20070C39A /* RJViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RJViewController.m; sourceTree = ""; };
56 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
57 | 6003F5AE195388D20070C39A /* RJBadgeKit_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RJBadgeKit_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
58 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
59 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; };
60 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
61 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; };
62 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; };
63 | 637DF2DA6661A379648E30F1 /* Pods_RJBadgeKit_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RJBadgeKit_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
64 | 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
65 | 756E1D2C28ADE93AB7B9EB7D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
66 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; };
67 | 94DE14D21FECDD4B00A7FCB3 /* RJDemoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RJDemoViewController.h; sourceTree = ""; };
68 | 94DE14D31FECDD4B00A7FCB3 /* RJDemoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RJDemoViewController.m; sourceTree = ""; };
69 | 94DE14D51FECDD5C00A7FCB3 /* RJDetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RJDetailViewController.h; sourceTree = ""; };
70 | 94DE14D61FECDD5C00A7FCB3 /* RJDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RJDetailViewController.m; sourceTree = ""; };
71 | A0A17E187F67450CBDC335FF /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
72 | DCA2EF8D8FA5BE88C7574C6E /* Pods-RJBadgeKit_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RJBadgeKit_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example.release.xcconfig"; sourceTree = ""; };
73 | E0E8882489A2C9C1186A2792 /* RJBadgeKit.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = RJBadgeKit.podspec; path = ../RJBadgeKit.podspec; sourceTree = ""; };
74 | E6AB50A9B5D6DEF251B477CB /* Pods-RJBadgeKit_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RJBadgeKit_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example.debug.xcconfig"; sourceTree = ""; };
75 | F4A5749C6C7DE87426F053B7 /* Pods-RJBadgeKit_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RJBadgeKit_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests.debug.xcconfig"; sourceTree = ""; };
76 | /* End PBXFileReference section */
77 |
78 | /* Begin PBXFrameworksBuildPhase section */
79 | 6003F587195388D20070C39A /* Frameworks */ = {
80 | isa = PBXFrameworksBuildPhase;
81 | buildActionMask = 2147483647;
82 | files = (
83 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
84 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
85 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
86 | 0DD0F3191BF43C6EF9F153DD /* Pods_RJBadgeKit_Example.framework in Frameworks */,
87 | );
88 | runOnlyForDeploymentPostprocessing = 0;
89 | };
90 | 6003F5AB195388D20070C39A /* Frameworks */ = {
91 | isa = PBXFrameworksBuildPhase;
92 | buildActionMask = 2147483647;
93 | files = (
94 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
95 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
96 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
97 | E306F03EF3AB5DBDF40E4F5B /* Pods_RJBadgeKit_Tests.framework in Frameworks */,
98 | );
99 | runOnlyForDeploymentPostprocessing = 0;
100 | };
101 | /* End PBXFrameworksBuildPhase section */
102 |
103 | /* Begin PBXGroup section */
104 | 6003F581195388D10070C39A = {
105 | isa = PBXGroup;
106 | children = (
107 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
108 | 6003F593195388D20070C39A /* Example for RJBadgeKit */,
109 | 6003F5B5195388D20070C39A /* Tests */,
110 | 6003F58C195388D20070C39A /* Frameworks */,
111 | 6003F58B195388D20070C39A /* Products */,
112 | 63C28FB217854BFA6EBC3042 /* Pods */,
113 | );
114 | sourceTree = "";
115 | };
116 | 6003F58B195388D20070C39A /* Products */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 6003F58A195388D20070C39A /* RJBadgeKit_Example.app */,
120 | 6003F5AE195388D20070C39A /* RJBadgeKit_Tests.xctest */,
121 | );
122 | name = Products;
123 | sourceTree = "";
124 | };
125 | 6003F58C195388D20070C39A /* Frameworks */ = {
126 | isa = PBXGroup;
127 | children = (
128 | 6003F58D195388D20070C39A /* Foundation.framework */,
129 | 6003F58F195388D20070C39A /* CoreGraphics.framework */,
130 | 6003F591195388D20070C39A /* UIKit.framework */,
131 | 6003F5AF195388D20070C39A /* XCTest.framework */,
132 | 637DF2DA6661A379648E30F1 /* Pods_RJBadgeKit_Example.framework */,
133 | 03485BE7FF6C3D929E410387 /* Pods_RJBadgeKit_Tests.framework */,
134 | );
135 | name = Frameworks;
136 | sourceTree = "";
137 | };
138 | 6003F593195388D20070C39A /* Example for RJBadgeKit */ = {
139 | isa = PBXGroup;
140 | children = (
141 | 6003F59C195388D20070C39A /* RJAppDelegate.h */,
142 | 6003F59D195388D20070C39A /* RJAppDelegate.m */,
143 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */,
144 | 6003F5A5195388D20070C39A /* RJViewController.h */,
145 | 6003F5A6195388D20070C39A /* RJViewController.m */,
146 | 94DE14D21FECDD4B00A7FCB3 /* RJDemoViewController.h */,
147 | 94DE14D31FECDD4B00A7FCB3 /* RJDemoViewController.m */,
148 | 94DE14D51FECDD5C00A7FCB3 /* RJDetailViewController.h */,
149 | 94DE14D61FECDD5C00A7FCB3 /* RJDetailViewController.m */,
150 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */,
151 | 6003F5A8195388D20070C39A /* Images.xcassets */,
152 | 6003F594195388D20070C39A /* Supporting Files */,
153 | );
154 | name = "Example for RJBadgeKit";
155 | path = RJBadgeKit;
156 | sourceTree = "";
157 | };
158 | 6003F594195388D20070C39A /* Supporting Files */ = {
159 | isa = PBXGroup;
160 | children = (
161 | 6003F595195388D20070C39A /* RJBadgeKit-Info.plist */,
162 | 6003F596195388D20070C39A /* InfoPlist.strings */,
163 | 6003F599195388D20070C39A /* main.m */,
164 | 6003F59B195388D20070C39A /* RJBadgeKit-Prefix.pch */,
165 | );
166 | name = "Supporting Files";
167 | sourceTree = "";
168 | };
169 | 6003F5B5195388D20070C39A /* Tests */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 6003F5BB195388D20070C39A /* Tests.m */,
173 | 6003F5B6195388D20070C39A /* Supporting Files */,
174 | );
175 | path = Tests;
176 | sourceTree = "";
177 | };
178 | 6003F5B6195388D20070C39A /* Supporting Files */ = {
179 | isa = PBXGroup;
180 | children = (
181 | 6003F5B7195388D20070C39A /* Tests-Info.plist */,
182 | 6003F5B8195388D20070C39A /* InfoPlist.strings */,
183 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
184 | );
185 | name = "Supporting Files";
186 | sourceTree = "";
187 | };
188 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
189 | isa = PBXGroup;
190 | children = (
191 | E0E8882489A2C9C1186A2792 /* RJBadgeKit.podspec */,
192 | A0A17E187F67450CBDC335FF /* README.md */,
193 | 756E1D2C28ADE93AB7B9EB7D /* LICENSE */,
194 | );
195 | name = "Podspec Metadata";
196 | sourceTree = "";
197 | };
198 | 63C28FB217854BFA6EBC3042 /* Pods */ = {
199 | isa = PBXGroup;
200 | children = (
201 | E6AB50A9B5D6DEF251B477CB /* Pods-RJBadgeKit_Example.debug.xcconfig */,
202 | DCA2EF8D8FA5BE88C7574C6E /* Pods-RJBadgeKit_Example.release.xcconfig */,
203 | F4A5749C6C7DE87426F053B7 /* Pods-RJBadgeKit_Tests.debug.xcconfig */,
204 | 26DDFFA3B26F1ABE8A296A1F /* Pods-RJBadgeKit_Tests.release.xcconfig */,
205 | );
206 | name = Pods;
207 | sourceTree = "";
208 | };
209 | /* End PBXGroup section */
210 |
211 | /* Begin PBXNativeTarget section */
212 | 6003F589195388D20070C39A /* RJBadgeKit_Example */ = {
213 | isa = PBXNativeTarget;
214 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "RJBadgeKit_Example" */;
215 | buildPhases = (
216 | D8B5F42091E997700F548D0B /* [CP] Check Pods Manifest.lock */,
217 | 6003F586195388D20070C39A /* Sources */,
218 | 6003F587195388D20070C39A /* Frameworks */,
219 | 6003F588195388D20070C39A /* Resources */,
220 | 81C8C47097FA3DAB0729D8EF /* [CP] Embed Pods Frameworks */,
221 | ED8EB6AC6E460EFD2BF2D572 /* [CP] Copy Pods Resources */,
222 | );
223 | buildRules = (
224 | );
225 | dependencies = (
226 | );
227 | name = RJBadgeKit_Example;
228 | productName = RJBadgeKit;
229 | productReference = 6003F58A195388D20070C39A /* RJBadgeKit_Example.app */;
230 | productType = "com.apple.product-type.application";
231 | };
232 | 6003F5AD195388D20070C39A /* RJBadgeKit_Tests */ = {
233 | isa = PBXNativeTarget;
234 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "RJBadgeKit_Tests" */;
235 | buildPhases = (
236 | 54619BFC1372C83B9822F361 /* [CP] Check Pods Manifest.lock */,
237 | 6003F5AA195388D20070C39A /* Sources */,
238 | 6003F5AB195388D20070C39A /* Frameworks */,
239 | 6003F5AC195388D20070C39A /* Resources */,
240 | F509852CB84B9412A22B32B1 /* [CP] Embed Pods Frameworks */,
241 | 82FEA02A08CBC1D9F6A4EEBE /* [CP] Copy Pods Resources */,
242 | );
243 | buildRules = (
244 | );
245 | dependencies = (
246 | 6003F5B4195388D20070C39A /* PBXTargetDependency */,
247 | );
248 | name = RJBadgeKit_Tests;
249 | productName = RJBadgeKitTests;
250 | productReference = 6003F5AE195388D20070C39A /* RJBadgeKit_Tests.xctest */;
251 | productType = "com.apple.product-type.bundle.unit-test";
252 | };
253 | /* End PBXNativeTarget section */
254 |
255 | /* Begin PBXProject section */
256 | 6003F582195388D10070C39A /* Project object */ = {
257 | isa = PBXProject;
258 | attributes = {
259 | CLASSPREFIX = RJ;
260 | LastUpgradeCheck = 0920;
261 | ORGANIZATIONNAME = RylanJIN;
262 | TargetAttributes = {
263 | 6003F5AD195388D20070C39A = {
264 | TestTargetID = 6003F589195388D20070C39A;
265 | };
266 | };
267 | };
268 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "RJBadgeKit" */;
269 | compatibilityVersion = "Xcode 3.2";
270 | developmentRegion = English;
271 | hasScannedForEncodings = 0;
272 | knownRegions = (
273 | en,
274 | Base,
275 | );
276 | mainGroup = 6003F581195388D10070C39A;
277 | productRefGroup = 6003F58B195388D20070C39A /* Products */;
278 | projectDirPath = "";
279 | projectRoot = "";
280 | targets = (
281 | 6003F589195388D20070C39A /* RJBadgeKit_Example */,
282 | 6003F5AD195388D20070C39A /* RJBadgeKit_Tests */,
283 | );
284 | };
285 | /* End PBXProject section */
286 |
287 | /* Begin PBXResourcesBuildPhase section */
288 | 6003F588195388D20070C39A /* Resources */ = {
289 | isa = PBXResourcesBuildPhase;
290 | buildActionMask = 2147483647;
291 | files = (
292 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
293 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
294 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
295 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
296 | );
297 | runOnlyForDeploymentPostprocessing = 0;
298 | };
299 | 6003F5AC195388D20070C39A /* Resources */ = {
300 | isa = PBXResourcesBuildPhase;
301 | buildActionMask = 2147483647;
302 | files = (
303 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
304 | );
305 | runOnlyForDeploymentPostprocessing = 0;
306 | };
307 | /* End PBXResourcesBuildPhase section */
308 |
309 | /* Begin PBXShellScriptBuildPhase section */
310 | 54619BFC1372C83B9822F361 /* [CP] Check Pods Manifest.lock */ = {
311 | isa = PBXShellScriptBuildPhase;
312 | buildActionMask = 2147483647;
313 | files = (
314 | );
315 | inputPaths = (
316 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
317 | "${PODS_ROOT}/Manifest.lock",
318 | );
319 | name = "[CP] Check Pods Manifest.lock";
320 | outputPaths = (
321 | "$(DERIVED_FILE_DIR)/Pods-RJBadgeKit_Tests-checkManifestLockResult.txt",
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | shellPath = /bin/sh;
325 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
326 | showEnvVarsInLog = 0;
327 | };
328 | 81C8C47097FA3DAB0729D8EF /* [CP] Embed Pods Frameworks */ = {
329 | isa = PBXShellScriptBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | );
333 | inputPaths = (
334 | "${SRCROOT}/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-frameworks.sh",
335 | "${BUILT_PRODUCTS_DIR}/RJBadgeKit/RJBadgeKit.framework",
336 | );
337 | name = "[CP] Embed Pods Frameworks";
338 | outputPaths = (
339 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RJBadgeKit.framework",
340 | );
341 | runOnlyForDeploymentPostprocessing = 0;
342 | shellPath = /bin/sh;
343 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-frameworks.sh\"\n";
344 | showEnvVarsInLog = 0;
345 | };
346 | 82FEA02A08CBC1D9F6A4EEBE /* [CP] Copy Pods Resources */ = {
347 | isa = PBXShellScriptBuildPhase;
348 | buildActionMask = 2147483647;
349 | files = (
350 | );
351 | inputPaths = (
352 | );
353 | name = "[CP] Copy Pods Resources";
354 | outputPaths = (
355 | );
356 | runOnlyForDeploymentPostprocessing = 0;
357 | shellPath = /bin/sh;
358 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-resources.sh\"\n";
359 | showEnvVarsInLog = 0;
360 | };
361 | D8B5F42091E997700F548D0B /* [CP] Check Pods Manifest.lock */ = {
362 | isa = PBXShellScriptBuildPhase;
363 | buildActionMask = 2147483647;
364 | files = (
365 | );
366 | inputPaths = (
367 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
368 | "${PODS_ROOT}/Manifest.lock",
369 | );
370 | name = "[CP] Check Pods Manifest.lock";
371 | outputPaths = (
372 | "$(DERIVED_FILE_DIR)/Pods-RJBadgeKit_Example-checkManifestLockResult.txt",
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | shellPath = /bin/sh;
376 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
377 | showEnvVarsInLog = 0;
378 | };
379 | ED8EB6AC6E460EFD2BF2D572 /* [CP] Copy Pods Resources */ = {
380 | isa = PBXShellScriptBuildPhase;
381 | buildActionMask = 2147483647;
382 | files = (
383 | );
384 | inputPaths = (
385 | );
386 | name = "[CP] Copy Pods Resources";
387 | outputPaths = (
388 | );
389 | runOnlyForDeploymentPostprocessing = 0;
390 | shellPath = /bin/sh;
391 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RJBadgeKit_Example/Pods-RJBadgeKit_Example-resources.sh\"\n";
392 | showEnvVarsInLog = 0;
393 | };
394 | F509852CB84B9412A22B32B1 /* [CP] Embed Pods Frameworks */ = {
395 | isa = PBXShellScriptBuildPhase;
396 | buildActionMask = 2147483647;
397 | files = (
398 | );
399 | inputPaths = (
400 | );
401 | name = "[CP] Embed Pods Frameworks";
402 | outputPaths = (
403 | );
404 | runOnlyForDeploymentPostprocessing = 0;
405 | shellPath = /bin/sh;
406 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RJBadgeKit_Tests/Pods-RJBadgeKit_Tests-frameworks.sh\"\n";
407 | showEnvVarsInLog = 0;
408 | };
409 | /* End PBXShellScriptBuildPhase section */
410 |
411 | /* Begin PBXSourcesBuildPhase section */
412 | 6003F586195388D20070C39A /* Sources */ = {
413 | isa = PBXSourcesBuildPhase;
414 | buildActionMask = 2147483647;
415 | files = (
416 | 6003F59E195388D20070C39A /* RJAppDelegate.m in Sources */,
417 | 94DE14D71FECDD5C00A7FCB3 /* RJDetailViewController.m in Sources */,
418 | 94DE14D41FECDD4B00A7FCB3 /* RJDemoViewController.m in Sources */,
419 | 6003F5A7195388D20070C39A /* RJViewController.m in Sources */,
420 | 6003F59A195388D20070C39A /* main.m in Sources */,
421 | );
422 | runOnlyForDeploymentPostprocessing = 0;
423 | };
424 | 6003F5AA195388D20070C39A /* Sources */ = {
425 | isa = PBXSourcesBuildPhase;
426 | buildActionMask = 2147483647;
427 | files = (
428 | 6003F5BC195388D20070C39A /* Tests.m in Sources */,
429 | );
430 | runOnlyForDeploymentPostprocessing = 0;
431 | };
432 | /* End PBXSourcesBuildPhase section */
433 |
434 | /* Begin PBXTargetDependency section */
435 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
436 | isa = PBXTargetDependency;
437 | target = 6003F589195388D20070C39A /* RJBadgeKit_Example */;
438 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
439 | };
440 | /* End PBXTargetDependency section */
441 |
442 | /* Begin PBXVariantGroup section */
443 | 6003F596195388D20070C39A /* InfoPlist.strings */ = {
444 | isa = PBXVariantGroup;
445 | children = (
446 | 6003F597195388D20070C39A /* en */,
447 | );
448 | name = InfoPlist.strings;
449 | sourceTree = "";
450 | };
451 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
452 | isa = PBXVariantGroup;
453 | children = (
454 | 6003F5B9195388D20070C39A /* en */,
455 | );
456 | name = InfoPlist.strings;
457 | sourceTree = "";
458 | };
459 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = {
460 | isa = PBXVariantGroup;
461 | children = (
462 | 71719F9E1E33DC2100824A3D /* Base */,
463 | );
464 | name = LaunchScreen.storyboard;
465 | sourceTree = "";
466 | };
467 | /* End PBXVariantGroup section */
468 |
469 | /* Begin XCBuildConfiguration section */
470 | 6003F5BD195388D20070C39A /* Debug */ = {
471 | isa = XCBuildConfiguration;
472 | buildSettings = {
473 | ALWAYS_SEARCH_USER_PATHS = NO;
474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
475 | CLANG_CXX_LIBRARY = "libc++";
476 | CLANG_ENABLE_MODULES = YES;
477 | CLANG_ENABLE_OBJC_ARC = YES;
478 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
479 | CLANG_WARN_BOOL_CONVERSION = YES;
480 | CLANG_WARN_COMMA = YES;
481 | CLANG_WARN_CONSTANT_CONVERSION = YES;
482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
483 | CLANG_WARN_EMPTY_BODY = YES;
484 | CLANG_WARN_ENUM_CONVERSION = YES;
485 | CLANG_WARN_INFINITE_RECURSION = YES;
486 | CLANG_WARN_INT_CONVERSION = YES;
487 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
488 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
489 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
490 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
491 | CLANG_WARN_STRICT_PROTOTYPES = YES;
492 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
493 | CLANG_WARN_UNREACHABLE_CODE = YES;
494 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
495 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
496 | COPY_PHASE_STRIP = NO;
497 | ENABLE_STRICT_OBJC_MSGSEND = YES;
498 | ENABLE_TESTABILITY = YES;
499 | GCC_C_LANGUAGE_STANDARD = gnu99;
500 | GCC_DYNAMIC_NO_PIC = NO;
501 | GCC_NO_COMMON_BLOCKS = YES;
502 | GCC_OPTIMIZATION_LEVEL = 0;
503 | GCC_PREPROCESSOR_DEFINITIONS = (
504 | "DEBUG=1",
505 | "$(inherited)",
506 | );
507 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
508 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
509 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
510 | GCC_WARN_UNDECLARED_SELECTOR = YES;
511 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
512 | GCC_WARN_UNUSED_FUNCTION = YES;
513 | GCC_WARN_UNUSED_VARIABLE = YES;
514 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
515 | ONLY_ACTIVE_ARCH = YES;
516 | SDKROOT = iphoneos;
517 | TARGETED_DEVICE_FAMILY = "1,2";
518 | };
519 | name = Debug;
520 | };
521 | 6003F5BE195388D20070C39A /* Release */ = {
522 | isa = XCBuildConfiguration;
523 | buildSettings = {
524 | ALWAYS_SEARCH_USER_PATHS = NO;
525 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
526 | CLANG_CXX_LIBRARY = "libc++";
527 | CLANG_ENABLE_MODULES = YES;
528 | CLANG_ENABLE_OBJC_ARC = YES;
529 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
530 | CLANG_WARN_BOOL_CONVERSION = YES;
531 | CLANG_WARN_COMMA = YES;
532 | CLANG_WARN_CONSTANT_CONVERSION = YES;
533 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
534 | CLANG_WARN_EMPTY_BODY = YES;
535 | CLANG_WARN_ENUM_CONVERSION = YES;
536 | CLANG_WARN_INFINITE_RECURSION = YES;
537 | CLANG_WARN_INT_CONVERSION = YES;
538 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
539 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
540 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
541 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
542 | CLANG_WARN_STRICT_PROTOTYPES = YES;
543 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
544 | CLANG_WARN_UNREACHABLE_CODE = YES;
545 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
546 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
547 | COPY_PHASE_STRIP = YES;
548 | ENABLE_NS_ASSERTIONS = NO;
549 | ENABLE_STRICT_OBJC_MSGSEND = YES;
550 | GCC_C_LANGUAGE_STANDARD = gnu99;
551 | GCC_NO_COMMON_BLOCKS = YES;
552 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
553 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
554 | GCC_WARN_UNDECLARED_SELECTOR = YES;
555 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
556 | GCC_WARN_UNUSED_FUNCTION = YES;
557 | GCC_WARN_UNUSED_VARIABLE = YES;
558 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
559 | SDKROOT = iphoneos;
560 | TARGETED_DEVICE_FAMILY = "1,2";
561 | VALIDATE_PRODUCT = YES;
562 | };
563 | name = Release;
564 | };
565 | 6003F5C0195388D20070C39A /* Debug */ = {
566 | isa = XCBuildConfiguration;
567 | baseConfigurationReference = E6AB50A9B5D6DEF251B477CB /* Pods-RJBadgeKit_Example.debug.xcconfig */;
568 | buildSettings = {
569 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
570 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
571 | GCC_PREFIX_HEADER = "RJBadgeKit/RJBadgeKit-Prefix.pch";
572 | INFOPLIST_FILE = "RJBadgeKit/RJBadgeKit-Info.plist";
573 | MODULE_NAME = ExampleApp;
574 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
575 | PRODUCT_NAME = "$(TARGET_NAME)";
576 | WRAPPER_EXTENSION = app;
577 | };
578 | name = Debug;
579 | };
580 | 6003F5C1195388D20070C39A /* Release */ = {
581 | isa = XCBuildConfiguration;
582 | baseConfigurationReference = DCA2EF8D8FA5BE88C7574C6E /* Pods-RJBadgeKit_Example.release.xcconfig */;
583 | buildSettings = {
584 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
585 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
586 | GCC_PREFIX_HEADER = "RJBadgeKit/RJBadgeKit-Prefix.pch";
587 | INFOPLIST_FILE = "RJBadgeKit/RJBadgeKit-Info.plist";
588 | MODULE_NAME = ExampleApp;
589 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
590 | PRODUCT_NAME = "$(TARGET_NAME)";
591 | WRAPPER_EXTENSION = app;
592 | };
593 | name = Release;
594 | };
595 | 6003F5C3195388D20070C39A /* Debug */ = {
596 | isa = XCBuildConfiguration;
597 | baseConfigurationReference = F4A5749C6C7DE87426F053B7 /* Pods-RJBadgeKit_Tests.debug.xcconfig */;
598 | buildSettings = {
599 | BUNDLE_LOADER = "$(TEST_HOST)";
600 | FRAMEWORK_SEARCH_PATHS = (
601 | "$(SDKROOT)/Developer/Library/Frameworks",
602 | "$(inherited)",
603 | "$(DEVELOPER_FRAMEWORKS_DIR)",
604 | );
605 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
606 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
607 | GCC_PREPROCESSOR_DEFINITIONS = (
608 | "DEBUG=1",
609 | "$(inherited)",
610 | );
611 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
612 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
613 | PRODUCT_NAME = "$(TARGET_NAME)";
614 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RJBadgeKit_Example.app/RJBadgeKit_Example";
615 | WRAPPER_EXTENSION = xctest;
616 | };
617 | name = Debug;
618 | };
619 | 6003F5C4195388D20070C39A /* Release */ = {
620 | isa = XCBuildConfiguration;
621 | baseConfigurationReference = 26DDFFA3B26F1ABE8A296A1F /* Pods-RJBadgeKit_Tests.release.xcconfig */;
622 | buildSettings = {
623 | BUNDLE_LOADER = "$(TEST_HOST)";
624 | FRAMEWORK_SEARCH_PATHS = (
625 | "$(SDKROOT)/Developer/Library/Frameworks",
626 | "$(inherited)",
627 | "$(DEVELOPER_FRAMEWORKS_DIR)",
628 | );
629 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
630 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
631 | INFOPLIST_FILE = "Tests/Tests-Info.plist";
632 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
633 | PRODUCT_NAME = "$(TARGET_NAME)";
634 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RJBadgeKit_Example.app/RJBadgeKit_Example";
635 | WRAPPER_EXTENSION = xctest;
636 | };
637 | name = Release;
638 | };
639 | /* End XCBuildConfiguration section */
640 |
641 | /* Begin XCConfigurationList section */
642 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "RJBadgeKit" */ = {
643 | isa = XCConfigurationList;
644 | buildConfigurations = (
645 | 6003F5BD195388D20070C39A /* Debug */,
646 | 6003F5BE195388D20070C39A /* Release */,
647 | );
648 | defaultConfigurationIsVisible = 0;
649 | defaultConfigurationName = Release;
650 | };
651 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "RJBadgeKit_Example" */ = {
652 | isa = XCConfigurationList;
653 | buildConfigurations = (
654 | 6003F5C0195388D20070C39A /* Debug */,
655 | 6003F5C1195388D20070C39A /* Release */,
656 | );
657 | defaultConfigurationIsVisible = 0;
658 | defaultConfigurationName = Release;
659 | };
660 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "RJBadgeKit_Tests" */ = {
661 | isa = XCConfigurationList;
662 | buildConfigurations = (
663 | 6003F5C3195388D20070C39A /* Debug */,
664 | 6003F5C4195388D20070C39A /* Release */,
665 | );
666 | defaultConfigurationIsVisible = 0;
667 | defaultConfigurationName = Release;
668 | };
669 | /* End XCConfigurationList section */
670 | };
671 | rootObject = 6003F582195388D10070C39A /* Project object */;
672 | }
673 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit.xcodeproj/xcshareddata/xcschemes/RJBadgeKit-Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
66 |
68 |
74 |
75 |
76 |
77 |
78 |
79 |
85 |
87 |
93 |
94 |
95 |
96 |
98 |
99 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/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/RJBadgeKit/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 |
32 |
39 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
74 |
80 |
90 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
114 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/Images.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 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Example/RJBadgeKit/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/RJBadgeKit/Images.xcassets/badgeNew.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "badgeNew@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "filename" : "badgeNew@3x.png",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/Example/RJBadgeKit/Images.xcassets/badgeNew.imageset/badgeNew@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/Example/RJBadgeKit/Images.xcassets/badgeNew.imageset/badgeNew@2x.png
--------------------------------------------------------------------------------
/Example/RJBadgeKit/Images.xcassets/badgeNew.imageset/badgeNew@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/Example/RJBadgeKit/Images.xcassets/badgeNew.imageset/badgeNew@3x.png
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJAppDelegate.h
3 | // RJBadgeKit
4 | //
5 | // Created by RylanJIN on 12/22/2017.
6 | // Copyright (c) 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 |
11 | @interface RJAppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJAppDelegate.m
3 | // RJBadgeKit
4 | //
5 | // Created by RylanJIN on 12/22/2017.
6 | // Copyright (c) 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import "RJAppDelegate.h"
10 | #import "RJBadgeKit.h"
11 |
12 | @implementation RJAppDelegate
13 |
14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
15 | {
16 | // Override point for customization after application launch.
17 | UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
18 | UITabBarItem *more = tabVC.tabBar.items[1];
19 |
20 | NSString *demoPath = @"root.pbdemo";
21 |
22 | [RJBadgeController setBadgeForKeyPath:demoPath];
23 |
24 | // set tab bar item red dot
25 | [self.badgeController observePath:demoPath badgeView:more block:nil];
26 |
27 | return YES;
28 | }
29 |
30 | - (void)applicationWillResignActive:(UIApplication *)application
31 | {
32 | // 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.
33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
34 | }
35 |
36 | - (void)applicationDidEnterBackground:(UIApplication *)application
37 | {
38 | // 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.
39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
40 | }
41 |
42 | - (void)applicationWillEnterForeground:(UIApplication *)application
43 | {
44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
45 | }
46 |
47 | - (void)applicationDidBecomeActive:(UIApplication *)application
48 | {
49 | // 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.
50 | }
51 |
52 | - (void)applicationWillTerminate:(UIApplication *)application
53 | {
54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
55 | }
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJBadgeKit-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJBadgeKit-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #import
8 |
9 | #ifndef __IPHONE_5_0
10 | #warning "This project uses features only available in iOS SDK 5.0 and later."
11 | #endif
12 |
13 | #ifdef __OBJC__
14 | @import UIKit;
15 | @import Foundation;
16 | #endif
17 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJDemoViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJDemoViewController.h
3 | // RJBadgeKit_Example
4 | //
5 | // Created by Ryan Jin on 22/12/2017.
6 | // Copyright © 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RJDemoViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJDemoViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJDemoViewController.m
3 | // RJBadgeKit_Example
4 | //
5 | // Created by Ryan Jin on 22/12/2017.
6 | // Copyright © 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import "RJDemoViewController.h"
10 | #import "RJBadgeKit.h"
11 |
12 | NSString * const RJMarkPath = @"root.mark";
13 |
14 | @interface RJDemoViewController ()
15 |
16 | @property (weak, nonatomic) IBOutlet UIButton *pageButton;
17 |
18 | @end
19 |
20 | @implementation RJDemoViewController
21 |
22 | - (void)viewDidLoad
23 | {
24 | [super viewDidLoad];
25 | // Do any additional setup after loading the view.
26 | NSString *demoPath = @"root.pbdemo.page";
27 |
28 | [RJBadgeController setBadgeForKeyPath:demoPath];
29 |
30 | [self.badgeController observePath:demoPath badgeView:self.pageButton block:nil];
31 |
32 | UIButton *mark = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 12.0f, 25, 25.f)];
33 | mark.badgeOffset = CGPointMake(-2, 6);
34 |
35 | [RJBadgeController setBadgeForKeyPath:RJMarkPath];
36 |
37 | [self.badgeController observePath:RJMarkPath badgeView:mark block:nil];
38 |
39 | [mark setTitle:@"Mark" forState:UIControlStateNormal];
40 | [mark setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
41 | [mark addTarget:self action:@selector(markAction:) forControlEvents:(UIControlEventTouchUpInside)];
42 |
43 | UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:mark];
44 | self.navigationItem.rightBarButtonItem = barItem;
45 | }
46 |
47 | - (void)viewDidAppear:(BOOL)animated
48 | {
49 | [super viewDidAppear:animated];
50 | /**
51 | @note Example for refresh badge display of -'mark' button on navigation bar,
52 | which may not appear at first due to autolayout procedure of navigation items.
53 | */
54 | [self.badgeController refreshBadgeView];
55 | }
56 |
57 | - (void)markAction:(UIButton *)sender
58 | {
59 | BOOL needShow = [RJBadgeController statusForKeyPath:RJMarkPath];
60 | if (needShow) {
61 | [RJBadgeController clearBadgeForKeyPath:RJMarkPath];
62 | } else {
63 | [RJBadgeController setBadgeForKeyPath:RJMarkPath];
64 | }
65 | }
66 |
67 | - (void)didReceiveMemoryWarning {
68 | [super didReceiveMemoryWarning];
69 | // Dispose of any resources that can be recreated.
70 | }
71 |
72 | /*
73 | #pragma mark - Navigation
74 |
75 | // In a storyboard-based application, you will often want to do a little preparation before navigation
76 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
77 | // Get the new view controller using [segue destinationViewController].
78 | // Pass the selected object to the new view controller.
79 | }
80 | */
81 |
82 | @end
83 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJDetailViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJDetailViewController.h
3 | // RJBadgeKit_Example
4 | //
5 | // Created by Ryan Jin on 22/12/2017.
6 | // Copyright © 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RJDetailViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJDetailViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJDetailViewController.m
3 | // RJBadgeKit_Example
4 | //
5 | // Created by Ryan Jin on 22/12/2017.
6 | // Copyright © 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import "RJDetailViewController.h"
10 | #import "RJBadgeKit.h"
11 |
12 | NSString * const RJItemPath1 = @"root.pbdemo.page.item1";
13 | NSString * const RJItemPath2 = @"root.pbdemo.page.item2";
14 |
15 | @interface RJDetailViewController ()
16 |
17 | @property (weak, nonatomic) IBOutlet UIButton *item1;
18 | @property (weak, nonatomic) IBOutlet UIButton *item2;
19 |
20 | @end
21 |
22 | @implementation RJDetailViewController
23 |
24 | - (void)viewDidLoad
25 | {
26 | [super viewDidLoad];
27 | // Do any additional setup after loading the view.
28 | [RJBadgeController setBadgeForKeyPath:RJItemPath1];
29 | [RJBadgeController setBadgeForKeyPath:RJItemPath2];
30 |
31 | [self.badgeController observePath:RJItemPath1 badgeView:self.item1 block:nil];
32 | [self.badgeController observePath:RJItemPath2 badgeView:self.item2 block:nil];
33 |
34 | [self.item1 setBadgeImage:[UIImage imageNamed:@"badgeNew"]];
35 | }
36 |
37 | - (IBAction)clickItem1:(UIButton *)sender
38 | {
39 | BOOL needShow = [RJBadgeController statusForKeyPath:RJItemPath1];
40 | if (needShow) {
41 | [RJBadgeController clearBadgeForKeyPath:RJItemPath1];
42 | } else {
43 | [RJBadgeController setBadgeForKeyPath:RJItemPath1];
44 | }
45 | }
46 |
47 | - (IBAction)clickItem2:(UIButton *)sender
48 | {
49 | BOOL needShow = [RJBadgeController statusForKeyPath:RJItemPath2];
50 | if (needShow) {
51 | [RJBadgeController clearBadgeForKeyPath:RJItemPath2];
52 | } else {
53 | [RJBadgeController setBadgeForKeyPath:RJItemPath2];
54 | }
55 | }
56 |
57 | /*
58 | #pragma mark - Navigation
59 |
60 | // In a storyboard-based application, you will often want to do a little preparation before navigation
61 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
62 | // Get the new view controller using [segue destinationViewController].
63 | // Pass the selected object to the new view controller.
64 | }
65 | */
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJViewController.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 12/22/2017.
6 | // Copyright (c) 2017 Ryan Jin. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 |
11 | @interface RJViewController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/RJViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJViewController.h
3 | // RJBadgeKit
4 | //
5 | // Created by RylanJIN on 08/03/2017.
6 | // Copyright (c) 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | #import "RJViewController.h"
10 | #import "RJBadgeKit.h"
11 |
12 | NSString * const DEMO_PARENT_PATH = @"root.p365";
13 | NSString * const DEMO_CHILD_PATH1 = @"root.p365.test1";
14 | NSString * const DEMO_CHILD_PATH2 = @"root.p365.test2";
15 |
16 | @interface RJViewController ()
17 |
18 | @property (weak, nonatomic) IBOutlet UILabel *countLabel;
19 | @property (weak, nonatomic) IBOutlet UILabel *pathLabel;
20 | @property (weak, nonatomic) IBOutlet UITextField *countField;
21 | @property (weak, nonatomic) IBOutlet UIButton *parentButton;
22 | @property (weak, nonatomic) IBOutlet UIButton *childButton1;
23 | @property (weak, nonatomic) IBOutlet UIButton *childButton2;
24 |
25 | @end
26 |
27 | @implementation RJViewController
28 |
29 | - (void)viewDidLoad
30 | {
31 | [super viewDidLoad];
32 | // Do any additional setup after loading the view, typically from a nib.
33 | [self.countField setDelegate:self];
34 | [self.countField setKeyboardType:UIKeyboardTypeNumberPad];
35 |
36 | [self.pathLabel setText:DEMO_CHILD_PATH1];
37 |
38 | // self.parentButton.badgeOffset = CGPointMake(-50, 0);
39 | self.parentButton.badgeRadius = 5.f;
40 | self.parentButton.badgeBgColor = [UIColor blueColor];
41 |
42 | // observe parent button 'root.p365'
43 | [self.badgeController observePath:DEMO_PARENT_PATH
44 | badgeView:self.parentButton
45 | block:^(id observer, NSDictionary *info) {
46 | NSLog(@"root.p365 => %@", info);
47 | }];
48 |
49 | // observe child button 'root.p365.test1'
50 | [self.badgeController observePath:DEMO_CHILD_PATH1
51 | badgeView:self.childButton1
52 | block:^(RJViewController *observer, NSDictionary *info) {
53 | NSUInteger count = [info[RJBadgeCountKey] unsignedIntegerValue];
54 | [observer.countLabel setText:[NSString stringWithFormat:@"%lu", (unsigned long)count]];
55 | }];
56 |
57 | NSUInteger count = [RJBadgeController countForKeyPath:DEMO_CHILD_PATH1];
58 | [self.countLabel setText:[@(count) stringValue]];
59 |
60 | /**
61 | DEBUG FOR PARENT BADGE COUNTING
62 | */
63 | [RJBadgeController setBadgeForKeyPath:DEMO_CHILD_PATH2 count:2];
64 |
65 | // observe child button 'root.p365.test2'
66 | [self.badgeController observePath:DEMO_CHILD_PATH2 badgeView:self.childButton2 block:nil];
67 | }
68 |
69 | #pragma mark - Click Button
70 | - (IBAction)setBadgePathWithCount:(UIButton *)sender
71 | {
72 | [self.view endEditing:YES];
73 |
74 | if (!self.countField.text) return;
75 |
76 | [RJBadgeController setBadgeForKeyPath:DEMO_CHILD_PATH1
77 | count:[self.countField.text integerValue]];
78 | }
79 |
80 | - (IBAction)setBadgePath:(UIButton *)sender {
81 | [RJBadgeController setBadgeForKeyPath:DEMO_CHILD_PATH1];
82 | }
83 |
84 | - (IBAction)clearBadgePath:(UIButton *)sender {
85 | [RJBadgeController clearBadgeForKeyPath:DEMO_CHILD_PATH1];
86 | }
87 |
88 | - (IBAction)clickChildButton1:(UIButton *)sender
89 | {
90 | BOOL needShow = [RJBadgeController statusForKeyPath:DEMO_CHILD_PATH1];
91 | if (needShow) {
92 | [RJBadgeController clearBadgeForKeyPath:DEMO_CHILD_PATH1];
93 | } else {
94 | [RJBadgeController setBadgeForKeyPath:DEMO_CHILD_PATH1];
95 | }
96 | }
97 |
98 | - (IBAction)clickChildButton2:(UIButton *)sender
99 | {
100 | BOOL needShow = [RJBadgeController statusForKeyPath:DEMO_CHILD_PATH2];
101 | if (needShow) {
102 | [RJBadgeController clearBadgeForKeyPath:DEMO_CHILD_PATH2];
103 | } else {
104 | [RJBadgeController setBadgeForKeyPath:DEMO_CHILD_PATH2 count:2];
105 | }
106 | }
107 |
108 | - (IBAction)clickParentButton:(UIButton *)sender {
109 | [RJBadgeController clearBadgeForKeyPath:DEMO_PARENT_PATH forced:YES];
110 | }
111 |
112 | #pragma mark - UITextFieldDelegate
113 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
114 | replacementString:(NSString *)string {
115 | return [self validateNumber:string];
116 | }
117 |
118 | - (BOOL)validateNumber:(NSString *)number
119 | {
120 | BOOL res = YES;
121 | int i = 0;
122 |
123 | NSCharacterSet *tmpSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
124 |
125 | while (i < number.length) {
126 | NSString * string = [number substringWithRange:NSMakeRange(i, 1)];
127 | NSRange range = [string rangeOfCharacterFromSet:tmpSet];
128 | if (range.length == 0) { res = NO; break; }
129 |
130 | i++;
131 | }
132 | return res;
133 | }
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/RJBadgeKit/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // RJBadgeKit
4 | //
5 | // Created by RylanJIN on 12/22/2017.
6 | // Copyright (c) 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | @import UIKit;
10 | #import "RJAppDelegate.h"
11 |
12 | int main(int argc, char * argv[])
13 | {
14 | @autoreleasepool {
15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RJAppDelegate class]));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Example/Tests/Tests-Prefix.pch:
--------------------------------------------------------------------------------
1 | // The contents of this file are implicitly included at the beginning of every test case source file.
2 |
3 | #ifdef __OBJC__
4 |
5 |
6 |
7 | #endif
8 |
--------------------------------------------------------------------------------
/Example/Tests/Tests.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeKitTests.m
3 | // RJBadgeKitTests
4 | //
5 | // Created by RylanJIN on 12/22/2017.
6 | // Copyright (c) 2017 RylanJIN. All rights reserved.
7 | //
8 |
9 | @import XCTest;
10 |
11 | @interface Tests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation Tests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
36 |
--------------------------------------------------------------------------------
/Example/Tests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Example/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/Example/demo.gif
--------------------------------------------------------------------------------
/Example/path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/Example/path.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 RylanJIN
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
11 | all 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
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RJBadgeKit
2 |
3 | [](https://travis-ci.org/RylanJIN/RJBadgeKit)
4 | [](http://cocoapods.org/pods/RJBadgeKit)
5 | [](http://cocoapods.org/pods/RJBadgeKit)
6 | [](http://cocoapods.org/pods/RJBadgeKit)
7 |
8 | ## Example
9 |
10 | To run the example project, clone the repo, and run `pod install` from the Example directory first.
11 |
12 | ## Installation
13 |
14 | RJBadgeKit is available through [CocoaPods](http://cocoapods.org). To install
15 | it, simply add the following line to your Podfile:
16 |
17 | ```ruby
18 | pod 'RJBadgeKit'
19 | ```
20 |
21 | ## Introduction
22 |
23 | This is the code repository associated with blog article: https://juejin.im/post/5b80265de51d4538a31b4165
24 |
25 | RJBadgeKit是一套完整的小红点(消息推送提示)解决方案,使用场景为App某个功能块有内容更新或有未读消息时右上角会有小红点提示。RJBadgeKit支持**小红点**和**数字**显示两种形式,小红点也可以是**自定义图片**。 另外,提供多层级小红点的关联显示逻辑,比如微信tab上的小红点显示数字为聊天列表里未读消息的总和,只有所有未读消息都清空的情况下tab上的小红点才会消失。
26 |
27 | 
28 |
29 | RJBadgeKit的小红点所支持的路径格式为`root.xx.xx`, 小红点原则是父节点的小红点为子节点的小红点并集。root为默认的根路径。如下图所示,root.first为子路径,root.second为同级子路径。在纯红点模式下,root的小红点显示为root.first, root.second和root.third的并集,同理在数字显示模式下,root的badge数量为root.first, root.second和root.third的badge数量之和。而root.first的badge数量则又为root.first.firstA和root.first.firstB的和。
30 |
31 | 
32 |
33 | ## Useage
34 |
35 | RJBadgeKit的用法包括**a)** add observer **b)** set/clear badge **c)** show/hide badge, 接口分别如下所示:
36 |
37 | #### Add observer
38 |
39 | 假设我们有个促销页面,该促销有两个商品参与活动,则促销页面的路径可设置为root.promotion,促销页面内两个商品的路径分别设为root.promotion.item1, root.promotion.item2. 现在需要推送小红点消息给用户,在promotion的入口处的button需要显示小红点提示,当用户进入到promotion页面且分别点击了item1和item2后,promotion的小红点提示才消失。
40 |
41 | 首先我们在RJPromotionViewController里面对promotionButton添加路径的观察者,当该路径被set badge时候则显示小红点,clear badge时则隐藏小红点:
42 |
43 | ```
44 | [self.badgeController observePath:@"root.promotion"
45 | badgeView:promotionButton
46 | block:^(RJPromotionViewController *observer, NSDictionary *info) {
47 | // Use [observer doSomething] instead of [self doSomething] to avoid retain cycle in block
48 | // key path -> info[RJBadgePathKey] : badgeContoller所observe的路径
49 | // badge status -> info[RJBadgeShowKey] : 当前路径所对应的badge是否处于set状态(是否应该显示小红点)
50 | // badge count -> info[RJBadgeCountKey]: 当前路径所对应的badge数值(仅在badge为数值模式下有效)
51 | }];
52 | ```
53 |
54 | 这里需要注意的几点是:
55 |
56 | 1. self.badgeController为动态生成的属性,无需自己定义和初始化,RJBadgeKit为所有NSObject对象通过category添加了badgeController
57 | 2. 无需调用remove observer, RJBadgeKit通过自释放机制自动移除observer. 如果确实需要提前移除观察者,可以调用unobservePath接口
58 | 3. 为防止循环引用,在badge的block里面用参数observer来代替self, RJBadgeKit对observer(即self.badgeController的self)进行了weak化处理并通过block回调参数传出
59 |
60 | #### Set/clear badge
61 |
62 | 在上述例子中,当网络请求返回时发现有两个促销数据,则调用:
63 |
64 | ```
65 | [RJBadgeController setBadgeForKeyPath:@"root.promotion.item1"];
66 | [RJBadgeController setBadgeForKeyPath:@"root.promotion.item2"];
67 | ```
68 |
69 | 子节点的badge状态变化会触发父节点observe的block回调,所以上述两行代码执行后promotionButton会触发显示小红点。当然如果希望promotionButton不显示小红点,而是显示具体的促销数量,则可以直接如下调用:
70 |
71 | ```
72 | [RJBadgeController setBadgeForKeyPath:@"root.promotion" count:2];
73 | ```
74 |
75 | 如果promotion item下面还有子节点, 则调用:
76 |
77 | ```
78 | [RJBadgeController setBadgeForKeyPath:@"root.promotion.item1" count:5];
79 | ```
80 |
81 | 在这个情况下,promotionButton上显示的数值(亦即root.promotion路径对应的badge值)为root.promotion.item1和root.promotion.item2及其所有子节点的数值之和。当用户点击查看item1和item2后,分别调用clear badeg接口:
82 |
83 | ```
84 | [RJBadgeController clearBadgeForKeyPath:@"root.promotion.item1"];
85 | [RJBadgeController clearBadgeForKeyPath:@"root.promotion.item2"];
86 | ```
87 |
88 | 这时父节点root.promotion的badge自动clear, promotionButton的小红点会自动隐藏。如果希望在item1被clear后就强制清除root.promotion的badge, 则可以在clear item1后调用:
89 |
90 | ```
91 | [RJBadgeController clearBadgeForKeyPath:@"root.promotion" force:YES];
92 | ```
93 |
94 | 这样即使子节点的badge尚未全部清除,父节点也会被强制clear. P.S 正常情况下不应该去调用force:YES, 如果非要调用,可能是路径结构设计不合理了。
95 |
96 | #### Show/hide badge
97 |
98 | RJBadgeKit支持UIView, UITabBarItem和UIBarButtonItem的小红点显示。小红点类型则支持默认圆形小红点,数值和自定义view/图片。显示的优先级为number > custom view > red dot
99 |
100 | ```
101 | promotionButton.badgeOffset = CGPointMake(-50, 0); // 调整小红点的显示位置offset, 相对于右上角
102 |
103 | [self.promotionButton setBadgeImage:[UIImage imageNamed:@"badgeNew"]]; // 显示自定义的badge icon
104 |
105 | [self.promotionButton setCustomView:self.customBadgeView]; // 显示自定义的badge view
106 | ```
107 |
108 | 更详细的使用示例请参考RJBadgeKit的Example工程
109 |
110 | ## Author
111 |
112 | Ryan Jin, xiaojun.jin@outlook.com
113 |
114 | ## License
115 |
116 | RJBadgeKit is available under the MIT license. See the LICENSE file for more info.
117 |
--------------------------------------------------------------------------------
/RJBadgeKit.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint RJBadgeKit.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'RJBadgeKit'
11 | s.version = '0.2.5'
12 | s.summary = 'Red dot (version/message reminder) display and its management.'
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.description = <<-DESC
21 | A complete and lightweight solution for red dot (version/message reminder) display and its management.
22 | DESC
23 |
24 | s.homepage = 'https://github.com/RylanJIN/RJBadgeKit'
25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
26 | s.license = { :type => 'MIT', :file => 'LICENSE' }
27 | s.author = { 'Ryan Jin' => 'xiaojun.jin@outlook.com' }
28 | s.source = { :git => 'https://github.com/RylanJIN/RJBadgeKit.git', :tag => s.version.to_s }
29 | # s.social_media_url = 'https://twitter.com/'
30 |
31 | s.ios.deployment_target = '8.0'
32 |
33 | s.source_files = 'RJBadgeKit/Classes/**/*'
34 |
35 | # s.resource_bundles = {
36 | # 'RJBadgeKit' => ['RJBadgeKit/Assets/*.png']
37 | # }
38 |
39 | # s.public_header_files = 'Pod/Classes/**/*.h'
40 | # s.frameworks = 'UIKit', 'MapKit'
41 | # s.dependency 'AFNetworking', '~> 2.3'
42 | end
43 |
--------------------------------------------------------------------------------
/RJBadgeKit/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/RJBadgeKit/Assets/.gitkeep
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rjinxx/RJBadgeKit/16a167202658a035910fdc42dba1d215f53f9abd/RJBadgeKit/Classes/.gitkeep
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/NSObject+RJBadgeController.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+RJBadgeController.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import
9 | #import "RJBadgeController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface NSObject (RJBadgeController)
14 |
15 | @property (nonatomic, strong) RJBadgeController *badgeController;
16 |
17 | @end
18 |
19 | NS_ASSUME_NONNULL_END
20 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/NSObject+RJBadgeController.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSObject+RJBadgeController.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import "NSObject+RJBadgeController.h"
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | static void * NSObjectBadgeControllerKey = &NSObjectBadgeControllerKey;
14 |
15 | @implementation NSObject (RJBadgeController)
16 |
17 | - (RJBadgeController *)badgeController
18 | {
19 | id controller = objc_getAssociatedObject(self, NSObjectBadgeControllerKey);
20 | // lazily create the badgeController
21 | if (nil == controller) {
22 | controller = [RJBadgeController controllerWithObserver:self];
23 | self.badgeController = controller;
24 | }
25 | return controller;
26 | }
27 |
28 | - (void)setBadgeController:(RJBadgeController *)badgeController {
29 | objc_setAssociatedObject(self, NSObjectBadgeControllerKey, badgeController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
30 | }
31 |
32 | @end
33 |
34 | NS_ASSUME_NONNULL_END
35 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/RJBadgeController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeController.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import
9 | #import "RJBadgeView.h"
10 | #import "RJBadge.h"
11 |
12 | #ifndef RJBadgeKeyPath
13 | #define RJBadgeKeyPath(KEYPATH) \
14 | @(((void)(NO && ((void)KEYPATH, NO)), strchr(#KEYPATH, '.') + 1))
15 | #endif
16 |
17 | #ifndef RJBadgeClassKeyPath
18 | #define RJBadgeClassKeyPath(CLASS, KEYPATH) \
19 | @(((void)(NO && ((void)((CLASS *)(nil)).KEYPATH, NO)), #KEYPATH))
20 | #endif
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | extern NSString * const RJBadgePathKey;
25 | extern NSString * const RJBadgeCountKey;
26 | extern NSString * const RJBadgeShowKey;
27 |
28 | typedef void (^RJBadgeNotificationBlock)(id _Nullable observer, NSDictionary *info);
29 |
30 | @interface RJBadgeController : NSObject
31 |
32 | /**
33 | The observer notified on badge change. Specified on initialization.
34 | */
35 | @property (nullable, nonatomic, weak, readonly) id observer;
36 |
37 | #pragma mark - Initialize
38 |
39 | + (instancetype)controllerWithObserver:(nullable id)observer;
40 |
41 | - (instancetype)initWithObserver:(nullable id)observer NS_DESIGNATED_INITIALIZER;
42 |
43 | /**
44 | @abstract Initializes a new instance.
45 | @warning This method is unavaialble. Use 'initWithObserver:' instead.
46 | */
47 | + (instancetype)new NS_UNAVAILABLE;
48 |
49 | /**
50 | @abstract Initializes a new instance.
51 | @warning This method is unavaialble. Use 'initWithObserver:' instead.
52 | */
53 | - (instancetype)init NS_UNAVAILABLE;
54 |
55 | #pragma mark - Observe
56 |
57 | - (void)observePath:(NSString *)keyPath block:(RJBadgeNotificationBlock)block;
58 |
59 | - (void)observePath:(NSString *)keyPath badgeView:(nullable id)badgeView block:(nullable RJBadgeNotificationBlock)block;
60 |
61 | - (void)observePaths:(NSArray *)keyPaths block:(RJBadgeNotificationBlock)block;
62 |
63 | #pragma mark - Unobserve
64 |
65 | - (void)unobservePath:(NSString *)keyPath;
66 |
67 | - (void)unobserveAll;
68 |
69 | #pragma mark - Operation
70 |
71 | /**
72 | refresh all badge views associated with current -observer,
73 | aim to deal with situations / issue linked to auto-layout,
74 | e.g. set 'setBadgeForKeyPath' when layout hasn't done yet.
75 | */
76 | - (void)refreshBadgeView;
77 |
78 | + (void)setBadgeForKeyPath:(NSString *)keyPath;
79 | + (void)setBadgeForKeyPath:(NSString *)keyPath count:(NSUInteger)count;
80 |
81 | + (void)clearBadgeForKeyPath:(NSString *)keyPath;
82 | + (void)clearBadgeForKeyPath:(NSString *)keyPath forced:(BOOL)forced;
83 |
84 | + (BOOL)statusForKeyPath:(NSString *)keyPath;
85 |
86 | + (NSUInteger)countForKeyPath:(NSString *)keyPath;
87 |
88 | @end
89 |
90 | NS_ASSUME_NONNULL_END
91 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/RJBadgeController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeController.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import "RJBadgeController.h"
9 | #import "RJBadgeInfo.h"
10 | #import
11 | #import "RJBadgeManager.h"
12 |
13 | @interface RJBadgeController ()
14 |
15 | @property (nullable, nonatomic, weak) id observer;
16 |
17 | @end
18 |
19 | @implementation RJBadgeController {
20 | NSHashTable *_infos;
21 | pthread_mutex_t _lock;
22 | }
23 |
24 | #pragma mark - Lifecycle
25 |
26 | - (instancetype)initWithObserver:(nullable id)observer
27 | {
28 | self = [super init];
29 | if (self) {
30 | _infos = [[NSHashTable alloc] initWithOptions:NSPointerFunctionsStrongMemory |
31 | NSPointerFunctionsObjectPersonality
32 | capacity:0];
33 | pthread_mutex_init(&_lock, NULL);
34 | self.observer = observer;
35 | }
36 | return self;
37 | }
38 |
39 | + (instancetype)controllerWithObserver:(nullable id)observer {
40 | return [[self alloc] initWithObserver:observer];
41 | }
42 |
43 | - (void)dealloc
44 | {
45 | [self unobserveAll];
46 | pthread_mutex_destroy(&_lock);
47 | }
48 |
49 | #pragma mark - Observe
50 |
51 | - (void)observePath:(NSString *)keyPath block:(RJBadgeNotificationBlock)block
52 | {
53 | NSAssert(0 != keyPath.length && NULL != block, @"missing required parameters: keyPath:%@ block:%p", keyPath, block);
54 |
55 | if (0 == keyPath.length || NULL == block) return;
56 |
57 | // create info
58 | RJBadgeInfo *info = [[RJBadgeInfo alloc] initWithController:self keyPath:keyPath block:block];
59 |
60 | // observe object with info
61 | [self _observeWithInfo:info];
62 | }
63 |
64 | - (void)observePath:(NSString *)keyPath badgeView:(nullable id)badgeView block:(nullable RJBadgeNotificationBlock)block
65 | {
66 | NSAssert(0 != keyPath.length, @"missing required parameters: keyPath:%@", keyPath);
67 |
68 | if (0 == keyPath.length) return;
69 |
70 | // create info
71 | RJBadgeInfo *info = [[RJBadgeInfo alloc] initWithController:self keyPath:keyPath badgeView:badgeView block:block];
72 |
73 | // observe object with info
74 | [self _observeWithInfo:info];
75 | }
76 |
77 | - (void)observePaths:(NSArray *)keyPaths block:(RJBadgeNotificationBlock)block
78 | {
79 | NSAssert(0 != keyPaths.count && NULL != block, @"missing required parameters: keyPaths:%@ block:%p", keyPaths, block);
80 |
81 | if (0 == keyPaths.count || NULL == block) return;
82 |
83 | for (NSString *keyPath in keyPaths) {
84 | [self observePath:keyPath block:block];
85 | }
86 | }
87 |
88 | #pragma mark - Unobserve
89 |
90 | - (void)unobservePath:(NSString *)keyPath
91 | {
92 | // create representative info
93 | RJBadgeInfo *info = [[RJBadgeInfo alloc] initWithController:self keyPath:keyPath];
94 |
95 | // unobserve object property
96 | [self _unobserveWithInfo:info];
97 | }
98 |
99 | - (void)unobserveAll {
100 | [self _unobserveAll];
101 | }
102 |
103 | #pragma mark - Utilities
104 |
105 | - (void)_observeWithInfo:(RJBadgeInfo *)info
106 | {
107 | pthread_mutex_lock(&_lock);
108 |
109 | // check for info existence
110 | RJBadgeInfo *existingInfo = [_infos member:info];
111 |
112 | if (existingInfo) {
113 | // aleady exists, don't observe again
114 | pthread_mutex_unlock(&_lock); return;
115 | }
116 |
117 | // add info and oberve
118 | [_infos addObject:info];
119 |
120 | // unlock prior to callout
121 | pthread_mutex_unlock(&_lock);
122 |
123 | [[RJBadgeManager sharedManager] observeWithInfo:info];
124 | }
125 |
126 | - (void)_unobserveWithInfo:(RJBadgeInfo *)info
127 | {
128 | pthread_mutex_lock(&_lock);
129 |
130 | // lookup registered info instance
131 | RJBadgeInfo *registeredInfo = [_infos member:info];
132 |
133 | if (registeredInfo) {
134 | [_infos removeObject:registeredInfo];
135 | }
136 |
137 | pthread_mutex_unlock(&_lock);
138 |
139 | [[RJBadgeManager sharedManager] unobserveWithInfo:info];
140 | }
141 |
142 | - (void)_unobserveAll
143 | {
144 | pthread_mutex_lock(&_lock);
145 |
146 | NSHashTable *infos = [_infos copy];
147 |
148 | // clear table and map
149 | [_infos removeAllObjects];
150 |
151 | // unlock
152 | pthread_mutex_unlock(&_lock);
153 |
154 | [[RJBadgeManager sharedManager] unobserveWithInfos:infos];
155 | }
156 |
157 | #pragma mark - Properties
158 |
159 | - (NSString *)debugDescription
160 | {
161 | NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p", NSStringFromClass([self class]), self];
162 | [s appendFormat:@" observer:<%@:%p>", NSStringFromClass([_observer class]), _observer];
163 |
164 | pthread_mutex_lock(&_lock);
165 |
166 | if (0 != _infos.count) {
167 | [s appendString:@"\n "];
168 | }
169 |
170 | NSMutableArray *infoDescriptions = [NSMutableArray arrayWithCapacity:_infos.count];
171 |
172 | for (RJBadgeInfo *info in _infos) {
173 | [infoDescriptions addObject:info.debugDescription];
174 | }
175 |
176 | [s appendFormat:@"-> %@", infoDescriptions];
177 |
178 | pthread_mutex_unlock(&_lock);
179 |
180 | [s appendString:@">"];
181 |
182 | return s;
183 | }
184 |
185 | #pragma mark - Operation
186 |
187 | - (void)refreshBadgeView {
188 | [[RJBadgeManager sharedManager] refreshBadgeWithInfos:_infos];
189 | }
190 |
191 | + (void)setBadgeForKeyPath:(NSString *)keyPath
192 | {
193 | if (![keyPath length]) return;
194 |
195 | [[RJBadgeManager sharedManager] setBadgeForKeyPath:keyPath];
196 | }
197 |
198 | + (void)setBadgeForKeyPath:(NSString *)keyPath count:(NSUInteger)count
199 | {
200 | if (![keyPath length]) return;
201 |
202 | [[RJBadgeManager sharedManager] setBadgeForKeyPath:keyPath count:count];
203 | }
204 |
205 | + (void)clearBadgeForKeyPath:(NSString *)keyPath {
206 | [self clearBadgeForKeyPath:keyPath forced:NO];
207 | }
208 |
209 | + (void)clearBadgeForKeyPath:(NSString *)keyPath forced:(BOOL)forced
210 | {
211 | if (![keyPath length]) return;
212 |
213 | [[RJBadgeManager sharedManager] clearBadgeForKeyPath:keyPath forced:forced];
214 | }
215 |
216 | + (BOOL)statusForKeyPath:(NSString *)keyPath
217 | {
218 | if (![keyPath length]) return NO;
219 |
220 | return [[RJBadgeManager sharedManager] statusForKeyPath:keyPath];
221 | }
222 |
223 | + (NSUInteger)countForKeyPath:(NSString *)keyPath
224 | {
225 | if (![keyPath length]) return 0;
226 |
227 | return [[RJBadgeManager sharedManager] countForKeyPath:keyPath];
228 | }
229 |
230 | @end
231 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/RJBadgeManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeManager.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import
9 | #import "RJBadgeInfo.h"
10 | #import "RJBadgeModel.h"
11 |
12 | /** BADGE TREE PATH
13 | -root : root
14 | -first : root.first
15 | -firstA : root.first.firstA
16 | -firstB : root.first.firstB
17 | -sencond : root.second
18 | -secondA : root.second.secondA
19 | -third : root.third
20 | */
21 |
22 | NS_ASSUME_NONNULL_BEGIN
23 |
24 | extern NSString * const RJBadgeRootPath;
25 | extern NSString * const RJBadgeNameKey;
26 |
27 | @interface RJBadgeManager : NSObject
28 |
29 | #pragma mark - Initialize
30 |
31 | + (RJBadgeManager *)sharedManager;
32 |
33 | #pragma mark - Observe
34 |
35 | - (void)observeWithInfo:(nullable RJBadgeInfo *)info;
36 |
37 | #pragma mark - Unobserve
38 |
39 | - (void)unobserveWithInfo:(nullable RJBadgeInfo *)info;
40 |
41 | - (void)unobserveWithInfos:(nullable NSHashTable *)infos;
42 |
43 | #pragma mark - Operation
44 |
45 | - (void)refreshBadgeWithInfos:(NSHashTable *)infos;
46 |
47 | - (void)setBadgeForKeyPath:(NSString *)keyPath;
48 | - (void)setBadgeForKeyPath:(NSString *)keyPath count:(NSUInteger)count;
49 |
50 | - (void)clearBadgeForKeyPath:(NSString *)keyPath;
51 | - (void)clearBadgeForKeyPath:(NSString *)keyPath forced:(BOOL)forced;
52 |
53 | - (BOOL)statusForKeyPath:(NSString *)keyPath;
54 |
55 | - (NSUInteger)countForKeyPath:(NSString *)keyPath;
56 |
57 | @end
58 |
59 | NS_ASSUME_NONNULL_END
60 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeController/RJBadgeManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeManager.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import "RJBadgeManager.h"
9 | #import
10 | #import "NSString+RJBadge.h"
11 | #import "UIBarButtonItem+RJBadge.h"
12 | #import "UITabBarItem+RJBadge.h"
13 | #import "UIView+RJBadge.h"
14 | #import "RJBadgeController.h"
15 |
16 | #ifndef dispatch_queue_async_rjbk
17 | #define dispatch_queue_async_rjbk(queue, block)\
18 | if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) { \
19 | block(); \
20 | } else { \
21 | dispatch_async(queue, block); \
22 | }
23 | #endif
24 |
25 | #ifndef dispatch_main_async_rjbk
26 | #define dispatch_main_async_rjbk(block) dispatch_queue_async_rjbk(dispatch_get_main_queue(), block)
27 | #endif
28 |
29 | NS_ASSUME_NONNULL_BEGIN
30 |
31 | @implementation RJBadgeManager {
32 | NSMutableDictionary *> *_objectInfosMap;
33 | RJBadgeModel *_root;
34 | pthread_mutex_t _mutex;
35 | dispatch_queue_t _badgeQueue;
36 | }
37 |
38 | #pragma mark - Lifecycle
39 |
40 | + (RJBadgeManager *)sharedManager
41 | {
42 | static RJBadgeManager *_badgeMgr;
43 | static dispatch_once_t onceToken;
44 | dispatch_once(&onceToken, ^{
45 | _badgeMgr = [RJBadgeManager new];
46 | });
47 |
48 | return _badgeMgr;
49 | }
50 |
51 | - (instancetype)init
52 | {
53 | self = [super init];
54 | if (nil != self) {
55 | // recursive lock
56 | pthread_mutexattr_t attr;
57 | pthread_mutexattr_init(&attr);
58 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
59 | pthread_mutex_init(&_mutex, &attr);
60 | pthread_mutexattr_destroy(&attr);
61 |
62 | _objectInfosMap = [[NSMutableDictionary alloc] initWithCapacity:0];
63 | _badgeQueue = dispatch_queue_create("com.badge.RJBadgeKit.queue", DISPATCH_QUEUE_CONCURRENT);
64 |
65 | [self setupRootBadge];
66 | }
67 | return self;
68 | }
69 |
70 | - (void)dealloc {
71 | pthread_mutex_destroy(&_mutex);
72 | }
73 |
74 | #pragma mark - Observe
75 |
76 | - (void)observeWithInfo:(nullable RJBadgeInfo *)info
77 | {
78 | if (nil == info) return;
79 |
80 | pthread_mutex_lock(&_mutex);
81 |
82 | NSString *keyPath = info.keyPath;
83 |
84 | // get observation infos
85 | NSMutableSet *infos = [_objectInfosMap objectForKey:keyPath];
86 |
87 | // lazilly create set of infos
88 | if (!infos) {
89 | infos = [NSMutableSet set];
90 | [_objectInfosMap setObject:infos forKey:keyPath];
91 | }
92 |
93 | // add info and oberve
94 | [infos addObject:info];
95 |
96 | // unlock prior to callout
97 | pthread_mutex_unlock(&_mutex);
98 |
99 | // case where need to show badge while adding the observer
100 | id badge = [self badgeForKeyPath:keyPath];
101 | if (badge && [badge needShow]) {
102 | [self statusChangeForBadges:@[badge]];
103 | }
104 | }
105 |
106 | #pragma mark - Unobserve
107 |
108 | - (void)unobserveWithInfo:(nullable RJBadgeInfo *)info
109 | {
110 | if (nil == info) return;
111 |
112 | pthread_mutex_lock(&_mutex);
113 |
114 | NSString *keyPath = info.keyPath;
115 |
116 | // get observation infos
117 | NSMutableSet *infos = [_objectInfosMap objectForKey:keyPath];
118 |
119 | // lookup registered info instance
120 | RJBadgeInfo *registeredInfo = [infos member:info];
121 | id badgeView = registeredInfo.badgeView;
122 |
123 | if (nil != registeredInfo) {
124 | [infos removeObject:registeredInfo];
125 |
126 | // remove no longer used infos
127 | if (0 == infos.count) {
128 | [_objectInfosMap removeObjectForKey:keyPath];
129 | }
130 | }
131 |
132 | // unlock
133 | pthread_mutex_unlock(&_mutex);
134 |
135 | if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
136 | dispatch_main_async_rjbk(^{ [badgeView hideBadge]; });
137 | }
138 | }
139 |
140 | - (void)unobserveWithInfos:(nullable NSHashTable *)infos
141 | {
142 | if (0 == infos.count) return;
143 |
144 | for (RJBadgeInfo *info in infos) {
145 | [self unobserveWithInfo:info];
146 | }
147 | }
148 |
149 | #pragma mark - Setup Badge
150 | - (void)setupRootBadge
151 | {
152 | NSString *badgeFile = [NSString badgeJSONPath];
153 | NSDictionary *badgeFileDic = [NSDictionary dictionaryWithContentsOfFile:badgeFile];
154 | NSDictionary *badgeDic = badgeFileDic ? : @{RJBadgeNameKey : @"root",
155 | RJBadgePathKey : @"root",
156 | RJBadgeCountKey: @(0),
157 | RJBadgeShowKey : @(YES)};
158 | _root = [RJBadgeModel initWithDictionary:badgeDic];
159 |
160 | if (!badgeFileDic) [self saveBadgeInfo];
161 | }
162 |
163 | - (void)saveBadgeInfo {
164 | [[_root dictionaryFormat] writeToFile:[NSString badgeJSONPath]
165 | atomically:YES];
166 | }
167 |
168 | #pragma mark - Set Badge
169 | - (void)setBadgeForKeyPath:(NSString *)keyPath {
170 | [self setBadgeForKeyPath:keyPath count:0];
171 | }
172 |
173 | - (void)setBadgeForKeyPath:(NSString *)keyPath count:(NSUInteger)count
174 | {
175 | if (!keyPath) return;
176 |
177 | NSArray *keyPathArray = [keyPath componentsSeparatedByString:@"."];
178 | NSMutableArray *notifyBadges = [NSMutableArray array];
179 |
180 | pthread_mutex_lock(&_mutex);
181 |
182 | id bParent = _root;
183 |
184 | for (NSString *name in keyPathArray) {
185 | if ([name isEqualToString:@"root"]) continue;
186 | id objFind = nil;
187 | for (id obj in bParent.children) {
188 | if ([obj.name isEqualToString:name]) {
189 | objFind = obj; break;
190 | }
191 | }
192 | NSString *namePath = [NSString stringWithFormat:@".%@",name];
193 | NSString *subKeyPath = [bParent.keyPath stringByAppendingString:namePath];
194 | if (!objFind) {
195 | BOOL set = ([name isEqualToString:[keyPathArray lastObject]]);
196 | objFind = [RJBadgeModel initWithDictionary:@{RJBadgeNameKey : name,
197 | RJBadgePathKey : subKeyPath,
198 | RJBadgeCountKey: @(0),
199 | RJBadgeShowKey : @(set)}];
200 | objFind.parent = bParent;
201 | [bParent addChild:objFind];
202 | }
203 | bParent = objFind;
204 | if ([subKeyPath isEqualToString:keyPath]) {
205 | objFind.needShow = YES;
206 | objFind.count = count;
207 | }
208 | [notifyBadges addObject:objFind];
209 | }
210 | [self saveBadgeInfo];
211 |
212 | pthread_mutex_unlock(&_mutex);
213 |
214 | [self statusChangeForBadges:[notifyBadges mutableCopy]];
215 | }
216 |
217 | #pragma mark - Clear Badge
218 | - (void)clearBadgeForKeyPath:(NSString *)keyPath {
219 | [self clearBadgeForKeyPath:keyPath forced:NO];
220 | }
221 |
222 | - (void)clearBadgeForKeyPath:(NSString *)keyPath forced:(BOOL)forced
223 | {
224 | if (!keyPath) return;
225 |
226 | NSArray *keyPathArray = [keyPath componentsSeparatedByString:@"."];
227 | NSMutableArray *notifyBadges = [NSMutableArray array];
228 |
229 | pthread_mutex_lock(&_mutex);
230 |
231 | id bParent = _root;
232 |
233 | for (NSString *name in keyPathArray) {
234 | if ([name isEqualToString:@"root"]) continue;
235 | id objFind = nil;
236 | for (id obj in bParent.children) {
237 | if ([obj.name isEqualToString:name]) {
238 | objFind = obj; bParent = objFind;
239 | break;
240 | }
241 | }
242 | if (!objFind) {
243 | pthread_mutex_unlock(&_mutex);
244 | return;
245 | }
246 | if ([name isEqualToString:[keyPathArray lastObject]]) {
247 | objFind.needShow = NO;
248 | if ([objFind.children count] == 0 || forced) {
249 | if ([objFind.children count] && forced) {
250 | NSArray *bs = [objFind.allLinkChildren mutableCopy];
251 | [notifyBadges addObjectsFromArray:bs];
252 | [objFind clearAllChildren];
253 | }
254 | objFind.count = 0;
255 | [objFind removeFromParent];
256 | }
257 | [self saveBadgeInfo];
258 | }
259 | [notifyBadges addObject:objFind];
260 | }
261 | pthread_mutex_unlock(&_mutex);
262 |
263 | [self statusChangeForBadges:[notifyBadges mutableCopy]];
264 | }
265 |
266 | #pragma mark - Status Change
267 | - (void)statusChangeForBadges:(NSArray> *)badges
268 | {
269 | if (![badges count]) return;
270 |
271 | for (id badge in badges) {
272 | NSString *path = badge.keyPath;
273 |
274 | if ([path isEqualToString:RJBadgeRootPath]) continue;
275 |
276 | pthread_mutex_lock(&_mutex);
277 |
278 | NSMutableSet *infos = [[_objectInfosMap objectForKey:path] copy];
279 |
280 | pthread_mutex_unlock(&_mutex);
281 |
282 | [infos enumerateObjectsUsingBlock:^(RJBadgeInfo *bInfo, BOOL * _Nonnull stop) {
283 | id badgeView = bInfo.badgeView;
284 | if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
285 | NSUInteger c = badge.count;
286 | dispatch_main_async_rjbk(^{
287 | if (c > 0) {
288 | [badgeView showBadgeWithValue:c];
289 | } else if (badge.needShow) {
290 | [badgeView showBadge];
291 | } else {
292 | [badgeView hideBadge];
293 | }
294 | });
295 | }
296 | if (bInfo.block) {
297 | id observer = bInfo.controller.observer;
298 | bInfo.block(observer, @{ RJBadgePathKey : badge.keyPath,
299 | RJBadgeShowKey : @(badge.needShow),
300 | RJBadgeCountKey: @(badge.count) });
301 | }
302 | }];
303 | }
304 | }
305 |
306 | #pragma mark - Refresh Badge
307 | - (void)refreshBadgeWithInfos:(NSHashTable *)infos
308 | {
309 | if (0 == infos.count) return;
310 |
311 | for (RJBadgeInfo *bInfo in infos) {
312 | id badge = [self badgeForKeyPath:bInfo.keyPath];
313 | id badgeView = bInfo.badgeView;
314 | if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
315 | NSUInteger c = badge.count;
316 | dispatch_main_async_rjbk(^{
317 | if (c > 0) {
318 | [badgeView showBadgeWithValue:c];
319 | } else if (badge.needShow) {
320 | [badgeView showBadge];
321 | } else {
322 | [badgeView hideBadge];
323 | }
324 | });
325 | }
326 | }
327 | }
328 |
329 | #pragma mark - Badge Status
330 | - (BOOL)statusForKeyPath:(NSString *)keyPath {
331 | return [[self badgeForKeyPath:keyPath] needShow];
332 | }
333 |
334 | - (NSUInteger)countForKeyPath:(NSString *)keyPath
335 | {
336 | id badge = [self badgeForKeyPath:keyPath];
337 | return badge ? badge.count : 0;
338 | }
339 |
340 | #pragma mark - Helper
341 | - (id)badgeForKeyPath:(NSString *)keyPath
342 | {
343 | NSArray *kPaths = [keyPath componentsSeparatedByString:@"."];
344 | id badge = nil;
345 |
346 | pthread_mutex_lock(&_mutex);
347 |
348 | id bParent = _root;
349 |
350 | for (NSString *name in kPaths) {
351 | if ([name isEqualToString:RJBadgeRootPath]) {
352 | continue;
353 | }
354 | id objFind = nil;
355 | for (id obj in bParent.children) {
356 | if ([obj.name isEqualToString:name]) {
357 | objFind = obj; bParent = objFind;
358 | break;
359 | }
360 | }
361 |
362 | if (!objFind) {
363 | pthread_mutex_unlock(&_mutex);
364 | return nil;
365 | }
366 |
367 | badge = objFind;
368 | }
369 |
370 | pthread_mutex_unlock(&_mutex);
371 |
372 | return badge;
373 | }
374 |
375 | @end
376 |
377 | NS_ASSUME_NONNULL_END
378 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeModel/RJBadge.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadge.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @protocol RJBadge
14 |
15 | @required
16 |
17 | @property (strong, nonatomic, readonly) NSString *name; // e.g. 'badge'
18 | @property (strong, nonatomic, readonly) NSString *keyPath; // e.g. 'root.RJ.badge'
19 | /**
20 | 1. non-leaf node, sum of children
21 | 2. terminal node: return 'count'
22 | 3. setter valid for terminal node
23 | */
24 | @property (assign, nonatomic) NSUInteger count; // badge value
25 | /**
26 | 1. non-leaf node: has any children?
27 | 2. terminal node: return 'needShow'
28 | */
29 | @property (assign, nonatomic) BOOL needShow; // red dot
30 |
31 | // immediate children of current badge
32 | @property (strong, nonatomic, readonly) NSMutableArray> *children;
33 | // all linked children, including children's children
34 | @property (strong, nonatomic, readonly) NSMutableArray> *allLinkChildren;
35 |
36 | @property (weak, nonatomic) id parent;
37 |
38 | // regist nodes in terms of key path
39 | + (id)initWithDictionary:(NSDictionary *)dic;
40 |
41 | /**
42 | convert id object to dictionary,
43 | useful for, e.g. Data Persistence / Archive
44 | */
45 | - (NSDictionary *)dictionaryFormat;
46 |
47 | - (void)addChild:(id)child; // add leaf
48 | - (void)removeChild:(id)child; // cut leaf
49 | - (void)clearAllChildren; // clearAll
50 |
51 | - (void)removeFromParent; // [parent removeChild:self]
52 |
53 | @end
54 |
55 | NS_ASSUME_NONNULL_END
56 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeModel/RJBadgeInfo.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeInfo.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import
9 | #import "RJBadgeController.h"
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface RJBadgeInfo : NSObject
14 |
15 | @property (nonatomic, copy, readonly) NSString *keyPath;
16 | @property (nonatomic, weak, readonly) RJBadgeController *controller;
17 | @property (nonatomic, copy, readonly) RJBadgeNotificationBlock block;
18 |
19 | @property (nonatomic, strong, readonly) id badgeView;
20 |
21 | - (instancetype)initWithController:(RJBadgeController *)controller keyPath:(NSString *)keyPath;
22 |
23 | - (instancetype)initWithController:(RJBadgeController *)controller keyPath:(NSString *)keyPath
24 | block:(nullable RJBadgeNotificationBlock)block;
25 |
26 | - (instancetype)initWithController:(RJBadgeController *)controller
27 | keyPath:(NSString *)keyPath
28 | badgeView:(nullable id)badgeView
29 | block:(nullable RJBadgeNotificationBlock)block;
30 |
31 | @end
32 |
33 | NS_ASSUME_NONNULL_END
34 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeModel/RJBadgeInfo.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeInfo.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/12/2017.
6 | //
7 |
8 | #import "RJBadgeInfo.h"
9 |
10 | @interface RJBadgeInfo ()
11 |
12 | @property (nonatomic, copy) NSString *keyPath;
13 | @property (nonatomic, weak) RJBadgeController *controller;
14 | @property (nonatomic, copy) RJBadgeNotificationBlock block;
15 |
16 | @property (nonatomic, strong) id badgeView;
17 |
18 | @end
19 |
20 | @implementation RJBadgeInfo {
21 | NSUInteger _badgeHash;
22 | }
23 |
24 | #pragma mark - Initialize
25 |
26 | - (instancetype)initWithController:(RJBadgeController *)controller
27 | keyPath:(NSString *)keyPath
28 | badgeView:(nullable id)badgeView
29 | block:(nullable RJBadgeNotificationBlock)block
30 | action:(nullable SEL)action
31 | {
32 | self = [super init];
33 | if (self) {
34 | self.controller = controller;
35 | self.keyPath = keyPath;
36 | self.badgeView = badgeView;
37 | self.block = block;
38 |
39 | _badgeHash = self.keyPath.hash ^ self.controller.hash;
40 | }
41 | return self;
42 | }
43 |
44 | - (instancetype)initWithController:(RJBadgeController *)controller keyPath:(NSString *)keyPath {
45 | return [self initWithController:controller keyPath:keyPath badgeView:NULL block:NULL action:NULL];
46 | }
47 |
48 | - (instancetype)initWithController:(RJBadgeController *)controller keyPath:(NSString *)keyPath
49 | block:(nullable RJBadgeNotificationBlock)block {
50 | return [self initWithController:controller keyPath:keyPath badgeView:NULL block:block action:NULL];
51 | }
52 |
53 | - (instancetype)initWithController:(RJBadgeController *)controller
54 | keyPath:(NSString *)keyPath
55 | badgeView:(nullable id)badgeView
56 | block:(nullable RJBadgeNotificationBlock)block {
57 | return [self initWithController:controller keyPath:keyPath badgeView:badgeView block:block action:NULL];
58 | }
59 |
60 | #pragma mark - Properties
61 |
62 | - (NSUInteger)hash {
63 | // hash must be consistent during the object's life time
64 | return _badgeHash/* [_keyPath hash] ^ [_controller hash] */;
65 | }
66 |
67 | - (BOOL)isEqual:(id)object
68 | {
69 | if (nil == object) {
70 | return NO;
71 | }
72 | if (self == object) {
73 | return YES;
74 | }
75 | if (![object isKindOfClass:[self class]]) {
76 | return NO;
77 | }
78 | RJBadgeInfo *badgeObj = (RJBadgeInfo *)object;
79 | BOOL isEqualPath = [_keyPath isEqualToString:badgeObj->_keyPath];
80 | BOOL isEqualController = (_controller == badgeObj->_controller);
81 |
82 | return isEqualPath && isEqualController;
83 | }
84 |
85 | - (NSString *)debugDescription
86 | {
87 | NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p keyPath:%@",
88 | NSStringFromClass([self class]), self, _keyPath];
89 | if (NULL != _block) {
90 | [s appendFormat:@" block:%p", _block];
91 | }
92 |
93 | [s appendString:@">"];
94 |
95 | return s;
96 | }
97 |
98 | @end
99 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeModel/RJBadgeModel.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeModel.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 | #import "RJBadge.h"
11 |
12 | @interface RJBadgeModel : NSObject
13 |
14 | @property (strong, nonatomic, readonly) NSString *name; // e.g. 'badge'
15 | @property (strong, nonatomic, readonly) NSString *keyPath; // e.g. 'root.RJ.badge'
16 | /**
17 | 1. non-leaf node, sum of children
18 | 2. terminal node: return 'count'
19 | 3. setter valid for terminal node
20 | */
21 | @property (assign, nonatomic) NSUInteger count; // badge value
22 | /**
23 | 1. non-leaf node: has any children?
24 | 2. terminal node: return 'needShow'
25 | */
26 | @property (assign, nonatomic) BOOL needShow; // red dot
27 |
28 | // immediate children of current badge
29 | @property (strong, nonatomic, readonly) NSMutableArray> *children;
30 | // all linked children, including children's children
31 | @property (strong, nonatomic, readonly) NSMutableArray> *allLinkChildren;
32 |
33 | @property (weak, nonatomic) id parent;
34 |
35 | // regist nodes in terms of key path
36 | + (id)initWithDictionary:(NSDictionary *)dic;
37 |
38 | /**
39 | convert id object to dictionary,
40 | useful for, e.g. Data Persistence / Archive
41 | */
42 | - (NSDictionary *)dictionaryFormat;
43 |
44 | - (void)addChild:(id)child; // add leaf
45 | - (void)removeChild:(id)child; // cut leaf
46 | - (void)clearAllChildren; // clearAll
47 |
48 | - (void)removeFromParent; // [parent removeChild:self]
49 |
50 | @end
51 |
52 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeModel/RJBadgeModel.m:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeModel.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import "RJBadgeModel.h"
10 | #import
11 |
12 | NSString * const RJBadgeRootPath = @"root";
13 |
14 | NSString * const RJBadgeNameKey = @"RJBadgeNameKey";
15 | NSString * const RJBadgePathKey = @"RJBadgePathKey";
16 | NSString * const RJBadgeChildrenKey = @"RJBadgeChildrenKey";
17 | NSString * const RJBadgeShowKey = @"RJBadgeShowKey";
18 | NSString * const RJBadgeCountKey = @"RJBadgeCountKey";
19 |
20 | @interface RJBadgeModel ()
21 |
22 | @property (strong, nonatomic, readwrite) NSString *name;
23 | @property (strong, nonatomic, readwrite) NSString *keyPath;
24 |
25 | @property (strong, nonatomic, readwrite) NSMutableArray> *children;
26 |
27 | @end
28 |
29 | @implementation RJBadgeModel {
30 | pthread_mutex_t _lock;
31 | }
32 |
33 | - (instancetype)initWithDictionary:(NSDictionary *)dic
34 | {
35 | self = [super init];
36 | if (self) {
37 | self.name = dic[RJBadgeNameKey];
38 | self.keyPath = dic[RJBadgePathKey];
39 |
40 | self.needShow = [dic[RJBadgeShowKey] boolValue];
41 | self.count = [dic[RJBadgeCountKey] unsignedIntegerValue];
42 | self.children = [[NSMutableArray alloc] init];
43 |
44 | NSArray *children = dic[RJBadgeChildrenKey];
45 | if (children) {
46 | [children enumerateObjectsUsingBlock:^(NSDictionary *child,
47 | NSUInteger idx,
48 | BOOL *stop) {
49 | RJBadgeModel *obj = [RJBadgeModel initWithDictionary:child];
50 | if (obj) {obj.parent = self; [self.children addObject:obj];}
51 | }];
52 | }
53 | pthread_mutex_init(&_lock, NULL);
54 | }
55 | return self;
56 | }
57 |
58 | - (id)copyWithZone:(NSZone *)zone
59 | {
60 | RJBadgeModel *model = [[[self class] alloc] init];
61 |
62 | model.name = self.name;
63 | model.keyPath = self.keyPath;
64 | model.count = self.count;
65 | model.needShow = self.needShow;
66 | model.parent = self.parent;
67 | model.children = [self.children mutableCopy];
68 |
69 | return model;
70 | }
71 |
72 | - (void)dealloc {
73 | pthread_mutex_destroy(&_lock);
74 | }
75 |
76 | - (NSString *)debugDescription
77 | {
78 | NSMutableString *s = [NSMutableString stringWithFormat:@"<%@:%p keyPath:%@", NSStringFromClass([self class]),
79 | self, _keyPath];
80 | [s appendFormat:@" count:%@", [@(_count) stringValue]];
81 | [s appendFormat:@" needShow:%@", [@(_needShow) stringValue]];
82 |
83 | if (NULL != _name) {
84 | [s appendFormat:@" name:%@", _name];
85 | }
86 | if (NULL != _parent) {
87 | [s appendFormat:@" parent.path:%@", _parent.keyPath];
88 | }
89 | if ([_children count]) {
90 | NSMutableArray *subPaths = [NSMutableArray array];
91 | for (RJBadgeModel *child in _children) {
92 | [subPaths addObject:child.keyPath];
93 | }
94 | [s appendFormat:@" children.path:%@", subPaths];
95 | }
96 | [s appendString:@">"];
97 |
98 | return s;
99 | }
100 |
101 | #pragma mark - RJBadge
102 | + (id)initWithDictionary:(NSDictionary *)dic
103 | {
104 | if (![dic count]) return nil;
105 |
106 | return [[RJBadgeModel alloc] initWithDictionary:dic];
107 | }
108 |
109 | - (void)addChild:(id)child
110 | {
111 | pthread_mutex_lock(&_lock);
112 |
113 | if (child) [self.children addObject:child];
114 |
115 | pthread_mutex_unlock(&_lock);
116 | }
117 |
118 | - (void)removeChild:(id)child
119 | {
120 | pthread_mutex_lock(&_lock);
121 |
122 | if ([self.children containsObject:child]) {
123 | [self.children removeObject:child];
124 | if (![self.children count]) {
125 | self.needShow = NO;
126 | self.count = 0;
127 | }
128 | }
129 |
130 | pthread_mutex_unlock(&_lock);
131 | }
132 |
133 | - (void)clearAllChildren;
134 | {
135 | pthread_mutex_lock(&_lock);
136 |
137 | NSArray *children = [self.children copy];
138 |
139 | [self.children removeAllObjects];
140 |
141 | pthread_mutex_unlock(&_lock);
142 |
143 | for (id child in children) {
144 | child.needShow = NO;
145 | child.count = 0;
146 | [child clearAllChildren];
147 | }
148 | }
149 |
150 | - (void)removeFromParent
151 | {
152 | if (self.parent) {
153 | [self.parent removeChild:self];
154 | self.parent = nil;
155 | }
156 | }
157 |
158 | - (NSDictionary *)dictionaryFormat
159 | {
160 | NSMutableDictionary *dic = [NSMutableDictionary new];
161 |
162 | if (self.name) dic[RJBadgeNameKey] = self.name;
163 | if (self.keyPath) dic[RJBadgePathKey] = self.keyPath;
164 | if (self.count) dic[RJBadgeCountKey] = @(self.count);
165 | if (self.needShow) dic[RJBadgeShowKey] = @(self.needShow);
166 |
167 | if ([self.children count]) {
168 | NSMutableArray *children = [NSMutableArray new];
169 | dic[RJBadgeChildrenKey] = children;
170 | [self.children enumerateObjectsUsingBlock:^(id obj,
171 | NSUInteger idx,
172 | BOOL *stop) {
173 | [children addObject:[obj dictionaryFormat]];
174 | }];
175 | }
176 | return dic;
177 | }
178 |
179 | #pragma mark - setter/getter
180 | - (BOOL)needShow
181 | {
182 | if ([self.children count]) {
183 | for (id badge in self.children) {
184 | if (badge.needShow) return YES;
185 | }
186 | return NO;
187 | }
188 | return _needShow;
189 | }
190 |
191 | - (NSUInteger)count
192 | {
193 | if ([self.children count]) {
194 | __block NSUInteger subCount = 0;
195 | [self.children enumerateObjectsUsingBlock:^(id obj,
196 | NSUInteger idx,
197 | BOOL *stop) {
198 | subCount += obj.count;
199 | }];
200 | _count = subCount;
201 | }
202 | return _count;
203 | }
204 |
205 | - (NSMutableArray> *)allLinkChildren
206 | {
207 | NSMutableArray *links = [self.children mutableCopy];
208 |
209 | if ([self.children count]) {
210 | [self.children enumerateObjectsUsingBlock:^(id obj,
211 | NSUInteger idx,
212 | BOOL *stop) {
213 | [links addObjectsFromArray:obj.allLinkChildren];
214 | }];
215 | }
216 | return links;
217 | }
218 |
219 | @end
220 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/RJBadgeView.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeView.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 |
11 | /**
12 | priority: number > custom view > red dot
13 | */
14 |
15 | @protocol RJBadgeView
16 |
17 | @required
18 |
19 | @property (nonatomic, strong) UILabel *badge;
20 | @property (nonatomic, strong) UIFont *badgeFont; // default bold size 9
21 | @property (nonatomic, strong) UIColor *badgeTextColor; // default white color
22 | @property (nonatomic, strong) UIColor *badgeBgColor;
23 | @property (nonatomic, assign) CGFloat badgeRadius; // for red dot mode
24 | @property (nonatomic, assign) CGPoint badgeOffset; // offset from right-top
25 |
26 | - (void)showBadge; // badge with red dot
27 | - (void)hideBadge;
28 |
29 | // badge with number, pass zero to hide badge
30 | - (void)showBadgeWithValue:(NSUInteger)value;
31 |
32 | @optional
33 |
34 | @property (nonatomic, strong) UIView *badgeCustomView;
35 | /**
36 | convenient interface:
37 | create 'cusomView' (UIImageView) using badgeImage
38 | view's size would simply be set as half of image.
39 | */
40 | @property (nonatomic, strong) UIImage *badgeImage;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UIBarButtonItem+RJBadge.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIBarButtonItem+RJBadge.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 | #import "RJBadgeView.h"
11 |
12 | @interface UIBarButtonItem (RJBadge)
13 |
14 | - (void)showBadge; // badge with red dot
15 | - (void)hideBadge;
16 |
17 | // badge with number, pass zero to hide badge
18 | - (void)showBadgeWithValue:(NSUInteger)value;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UIBarButtonItem+RJBadge.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIBarButtonItem+RJBadge.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import "UIBarButtonItem+RJBadge.h"
10 | #import
11 | #import "UIView+RJBadge.h"
12 |
13 | @implementation UIBarButtonItem (RJBadge)
14 |
15 | #pragma mark - RJBadgeView
16 | - (void)showBadge {
17 | [[self badgeView] showBadge];
18 | }
19 | - (void)hideBadge {
20 | [[self badgeView] hideBadge];
21 | }
22 |
23 | - (void)showBadgeWithValue:(NSUInteger)value {
24 | [[self badgeView] showBadgeWithValue:value];
25 | }
26 |
27 | #pragma mark - private method
28 | - (UIView *)badgeView {
29 | return [self valueForKeyPath:@"_view"];
30 | }
31 |
32 | #pragma mark - setter/getter
33 | - (UILabel *)badge {
34 | return [self badgeView].badge;
35 | }
36 |
37 | - (void)setBadge:(UILabel *)label {
38 | [[self badgeView] setBadge:label];
39 | }
40 |
41 | - (UIFont *)badgeFont {
42 | return [self badgeView].badgeFont;
43 | }
44 |
45 | - (void)setBadgeFont:(UIFont *)badgeFont {
46 | [[self badgeView] setBadgeFont:badgeFont];
47 | }
48 |
49 | - (UIColor *)badgeTextColor {
50 | return [[self badgeView] badgeTextColor];
51 | }
52 |
53 | - (void)setBadgeTextColor:(UIColor *)badgeTextColor {
54 | [[self badgeView] setBadgeTextColor:badgeTextColor];
55 | }
56 |
57 | - (CGFloat)badgeRadius {
58 | return [[self badgeView] badgeRadius];
59 | }
60 |
61 | - (void)setBadgeRadius:(CGFloat)badgeRadius {
62 | [[self badgeView] setBadgeRadius:badgeRadius];
63 | }
64 |
65 | - (CGPoint)badgeOffset {
66 | return [[self badgeView] badgeOffset];
67 | }
68 |
69 | - (void)setBadgeOffset:(CGPoint)badgeOffset {
70 | [[self badgeView] setBadgeOffset:badgeOffset];
71 | }
72 |
73 | - (UIColor *)badgeBgColor {
74 | return [[self badgeView] badgeBgColor];
75 | }
76 |
77 | - (void)setBadgeBgColor:(UIColor *)badgeBgColor {
78 | [[self badgeView] setBadgeBgColor:badgeBgColor];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UITabBarItem+RJBadge.h:
--------------------------------------------------------------------------------
1 | //
2 | // UITabBarItem+RJBadge.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 | #import "RJBadgeView.h"
11 |
12 | @interface UITabBarItem (RJBadge)
13 |
14 | - (void)showBadge; // badge with red dot
15 | - (void)hideBadge;
16 |
17 | // badge with number, pass zero to hide badge
18 | - (void)showBadgeWithValue:(NSUInteger)value;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UITabBarItem+RJBadge.m:
--------------------------------------------------------------------------------
1 | //
2 | // UITabBarItem+RJBadge.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import "UITabBarItem+RJBadge.h"
10 | #import
11 | #import "UIView+RJBadge.h"
12 |
13 | @implementation UITabBarItem (RJBadge)
14 |
15 | #pragma mark - RJBadgeView
16 | - (void)showBadge {
17 | [[self badgeView] showBadge];
18 | }
19 | - (void)hideBadge {
20 | [[self badgeView] hideBadge];
21 | }
22 |
23 | - (void)showBadgeWithValue:(NSUInteger)value {
24 | [[self badgeView] showBadgeWithValue:value];
25 | }
26 |
27 | #pragma mark - private method
28 | - (UIView *)badgeView
29 | {
30 | UIView *bottomView = [self valueForKeyPath:@"_view"]; // UITabbarButtion
31 | UIView *parentView = nil; // UIImageView
32 | if (bottomView) {
33 | parentView = [self find:bottomView
34 | firstSubviewWithClass:NSClassFromString(@"UITabBarSwappableImageView")];
35 | }
36 | return parentView;
37 | }
38 |
39 | - (UIView *)find:(UIView *)view firstSubviewWithClass:(Class)cls
40 | {
41 | __block UIView *targetView = nil;
42 | [view.subviews enumerateObjectsUsingBlock:^(UIView *subview,
43 | NSUInteger idx,
44 | BOOL *stop) {
45 | if ([subview isKindOfClass:cls]) {
46 | targetView = subview; *stop = YES;
47 | }
48 | }];
49 | return targetView;
50 | }
51 |
52 | #pragma mark - setter/getter
53 | - (UILabel *)badge {
54 | return [self badgeView].badge;
55 | }
56 |
57 | - (void)setBadge:(UILabel *)label {
58 | [[self badgeView] setBadge:label];
59 | }
60 |
61 | - (UIFont *)badgeFont {
62 | return [self badgeView].badgeFont;
63 | }
64 |
65 | - (void)setBadgeFont:(UIFont *)badgeFont {
66 | [[self badgeView] setBadgeFont:badgeFont];
67 | }
68 |
69 | - (UIColor *)badgeTextColor {
70 | return [[self badgeView] badgeTextColor];
71 | }
72 |
73 | - (void)setBadgeTextColor:(UIColor *)badgeTextColor {
74 | [[self badgeView] setBadgeTextColor:badgeTextColor];
75 | }
76 |
77 | - (CGFloat)badgeRadius {
78 | return [[self badgeView] badgeRadius];
79 | }
80 |
81 | - (void)setBadgeRadius:(CGFloat)badgeRadius {
82 | [[self badgeView] setBadgeRadius:badgeRadius];
83 | }
84 |
85 | - (CGPoint)badgeOffset {
86 | return [[self badgeView] badgeOffset];
87 | }
88 |
89 | - (void)setBadgeOffset:(CGPoint)badgeOffset {
90 | [[self badgeView] setBadgeOffset:badgeOffset];
91 | }
92 |
93 | - (UIColor *)badgeBgColor {
94 | return [[self badgeView] badgeBgColor];
95 | }
96 |
97 | - (void)setBadgeBgColor:(UIColor *)badgeBgColor {
98 | [[self badgeView] setBadgeBgColor:badgeBgColor];
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UIView+RJBadge.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RJBadge.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import
10 | #import "RJBadgeView.h"
11 |
12 | @interface UIView (RJBadge)
13 |
14 | - (void)showBadge; // badge with red dot
15 | - (void)hideBadge;
16 |
17 | // badge with number, pass zero to hide badge
18 | - (void)showBadgeWithValue:(NSUInteger)value;
19 |
20 | @end
21 |
22 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/BadgeView/UIView+RJBadge.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIView+RJBadge.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #import "UIView+RJBadge.h"
10 | #import
11 |
12 | #define kRJBadgeDefaultFont ([UIFont boldSystemFontOfSize:9])
13 | #define kRJBadgeDefaultMaximumBadgeNumber 99
14 |
15 | static const CGFloat kRJBadgeDefaultRadius = 3.f;
16 |
17 | @implementation UIView (RJBadge)
18 |
19 | #pragma mark - RJBadgeView
20 | - (void)showBadge
21 | {
22 | CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
23 | CGPoint center = CGPointMake(offsetX, self.badgeOffset.y);
24 |
25 | if (self.badgeCustomView) {
26 | self.badgeCustomView.hidden = NO;
27 | self.badge.hidden = YES;
28 | self.badgeCustomView.center = center;
29 | } else {
30 | CGFloat w = (self.badgeRadius ? : kRJBadgeDefaultRadius) * 2;
31 | CGRect r = CGRectMake(CGRectGetWidth(self.frame), -w, w, w);
32 |
33 | self.badge.frame = r;
34 | self.badge.text = @"";
35 | self.badge.hidden = NO;
36 | self.badge.layer.cornerRadius = w / 2;
37 | self.badge.center = center;
38 | }
39 | }
40 |
41 | - (void)showBadgeWithValue:(NSUInteger)value
42 | {
43 | self.badgeCustomView.hidden = YES;
44 |
45 | self.badge.hidden = (value == 0);
46 | self.badge.font = self.badgeFont;
47 | self.badge.text = (value > kRJBadgeDefaultMaximumBadgeNumber ?
48 | [NSString stringWithFormat:@"%@+", @(kRJBadgeDefaultMaximumBadgeNumber)] :
49 | [NSString stringWithFormat:@"%@" , @(value)]);
50 | [self adjustLabelWidth:self.badge];
51 |
52 | CGRect frame = self.badge.frame;
53 | frame.size.width += 4;
54 | frame.size.height += 4;
55 |
56 | if(CGRectGetWidth(frame) < CGRectGetHeight(frame)) {
57 | frame.size.width = CGRectGetHeight(frame);
58 | }
59 | self.badge.frame = frame;
60 | CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
61 | self.badge.center = CGPointMake(offsetX, self.badgeOffset.y);
62 |
63 | self.badge.layer.cornerRadius = CGRectGetHeight(self.badge.frame) / 2.f;
64 | }
65 |
66 | - (void)hideBadge
67 | {
68 | if (self.badgeCustomView) {
69 | self.badgeCustomView.hidden = YES;
70 | }
71 | self.badge.hidden = YES;
72 | }
73 |
74 | #pragma mark - private methods
75 | - (void)adjustLabelWidth:(UILabel *)label
76 | {
77 | [label setNumberOfLines:0];
78 |
79 | NSString *s = label.text;
80 | UIFont *font = [label font];
81 | CGSize size = CGSizeMake(320,2000);
82 |
83 | CGSize labelsize = CGSizeZero;
84 |
85 | if (![s respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
86 | #pragma clang diagnostic push
87 | #pragma clang diagnostic ignored "-Wdeprecated-declarations"
88 | labelsize = [s sizeWithFont:font
89 | constrainedToSize:size
90 | lineBreakMode:NSLineBreakByWordWrapping];
91 | #pragma clang diagnostic pop
92 | } else {
93 | NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
94 | [style setLineBreakMode:NSLineBreakByWordWrapping];
95 |
96 | labelsize = [s boundingRectWithSize:size
97 | options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
98 | attributes:@{NSFontAttributeName: font, NSParagraphStyleAttributeName: style}
99 | context:nil].size;
100 | }
101 | CGRect frame = label.frame;
102 | frame.size = CGSizeMake(ceilf(labelsize.width), ceilf(labelsize.height));
103 | [label setFrame:frame];
104 | }
105 |
106 | #pragma mark - setter/getter
107 | - (UILabel *)badge
108 | {
109 | UILabel *bLabel = objc_getAssociatedObject(self, _cmd);
110 | if (!bLabel) {
111 | CGFloat width = kRJBadgeDefaultRadius * 2;
112 | CGRect rect = CGRectMake(CGRectGetWidth(self.frame), -width, width, width);
113 | bLabel = [[UILabel alloc] initWithFrame:rect];
114 | bLabel.textAlignment = NSTextAlignmentCenter;
115 | bLabel.backgroundColor = [UIColor colorWithRed: 1.f
116 | green: 93.f/225.f
117 | blue:165.f/255.f
118 | alpha:1.f];
119 | bLabel.textColor = [UIColor whiteColor];
120 | bLabel.text = @"";
121 | // CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
122 | // bLabel.center = CGPointMake(offsetX, self.badgeOffset.y);
123 |
124 | bLabel.layer.cornerRadius = kRJBadgeDefaultRadius;
125 | bLabel.layer.masksToBounds = YES;
126 | bLabel.hidden = YES;
127 |
128 | objc_setAssociatedObject(self,
129 | _cmd,
130 | bLabel,
131 | OBJC_ASSOCIATION_RETAIN_NONATOMIC);
132 | [self addSubview:bLabel];
133 | [self bringSubviewToFront:bLabel];
134 | }
135 | return bLabel;
136 | }
137 |
138 | - (void)setBadge:(UILabel *)badge {
139 | objc_setAssociatedObject(self,
140 | @selector(badge),
141 | badge,
142 | OBJC_ASSOCIATION_RETAIN);
143 | }
144 |
145 | - (UIFont *)badgeFont {
146 | return objc_getAssociatedObject(self, _cmd) ?: kRJBadgeDefaultFont;
147 | }
148 |
149 | - (void)setBadgeFont:(UIFont *)badgeFont
150 | {
151 | objc_setAssociatedObject(self,
152 | @selector(badgeFont),
153 | badgeFont,
154 | OBJC_ASSOCIATION_RETAIN);
155 | self.badge.font = badgeFont;
156 | }
157 |
158 | - (UIColor *)badgeBgColor {
159 | return objc_getAssociatedObject(self, _cmd);
160 | }
161 |
162 | - (void)setBadgeBgColor:(UIColor *)badgeBgColor
163 | {
164 | objc_setAssociatedObject(self,
165 | @selector(badgeBgColor),
166 | badgeBgColor,
167 | OBJC_ASSOCIATION_RETAIN);
168 | self.badge.backgroundColor = badgeBgColor;
169 | }
170 |
171 | - (UIColor *)badgeTextColor {
172 | return objc_getAssociatedObject(self, _cmd);
173 | }
174 |
175 | - (void)setBadgeTextColor:(UIColor *)badgeTextColor
176 | {
177 | objc_setAssociatedObject(self,
178 | @selector(badgeTextColor),
179 | badgeTextColor,
180 | OBJC_ASSOCIATION_RETAIN);
181 | self.badge.textColor = badgeTextColor;
182 | }
183 |
184 | - (CGFloat)badgeRadius {
185 | return [objc_getAssociatedObject(self, _cmd) floatValue];
186 | }
187 |
188 | - (void)setBadgeRadius:(CGFloat)badgeRadius {
189 | objc_setAssociatedObject(self,
190 | @selector(badgeRadius),
191 | @(badgeRadius),
192 | OBJC_ASSOCIATION_RETAIN);
193 | }
194 |
195 | - (CGPoint)badgeOffset
196 | {
197 | NSValue *offset = objc_getAssociatedObject(self, _cmd);
198 |
199 | if (!offset) return CGPointZero;
200 |
201 | return [offset CGPointValue];
202 | }
203 |
204 | - (void)setBadgeOffset:(CGPoint)badgeOffset {
205 | objc_setAssociatedObject(self,
206 | @selector(badgeOffset),
207 | [NSValue valueWithCGPoint:badgeOffset],
208 | OBJC_ASSOCIATION_RETAIN_NONATOMIC);
209 | }
210 |
211 | - (UIImage *)badgeImage {
212 | return objc_getAssociatedObject(self, _cmd);
213 | }
214 |
215 | - (void)setBadgeImage:(UIImage *)badgeImage
216 | {
217 | if (!badgeImage) {
218 | [self.badgeCustomView removeFromSuperview];
219 | [self setBadgeCustomView:nil];
220 | } else {
221 | self.badgeCustomView = [[UIImageView alloc] initWithImage:badgeImage];
222 | objc_setAssociatedObject(self,
223 | @selector(badgeImage),
224 | badgeImage,
225 | OBJC_ASSOCIATION_RETAIN);
226 | }
227 | }
228 |
229 | - (UIView *)badgeCustomView {
230 | return objc_getAssociatedObject(self, _cmd);
231 | }
232 |
233 | - (void)setBadgeCustomView:(UIView *)badgeCustomView
234 | {
235 | if (self.badgeCustomView == badgeCustomView) return;
236 |
237 | if (self.badgeCustomView) [self.badgeCustomView removeFromSuperview];
238 | if (badgeCustomView) [self addSubview:badgeCustomView];
239 |
240 | objc_setAssociatedObject(self,
241 | @selector(badgeCustomView),
242 | badgeCustomView,
243 | OBJC_ASSOCIATION_RETAIN_NONATOMIC);
244 | if (self.badgeCustomView) {
245 | CGRect bound = badgeCustomView.bounds;
246 | bound.origin.x = CGRectGetWidth(self.frame);
247 | bound.origin.y = -bound.size.height;
248 |
249 | self.badgeCustomView.frame = bound;
250 | self.badgeCustomView.hidden = YES;
251 | // CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
252 | // self.badgeCustomView.center = CGPointMake(offsetX, self.badgeOffset.y);
253 | }
254 | // [self showBadge]; // refresh - in case of setting custom view after show badge
255 | }
256 |
257 | @end
258 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/Helper/NSString+RJBadge.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+RJBadge.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/08/2017.
6 | //
7 | //
8 |
9 | #import
10 |
11 | @interface NSString (RJBadge)
12 |
13 | + (NSString *)badgeFilePath;
14 | + (NSString *)badgeJSONPath;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/Helper/NSString+RJBadge.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+RJBadge.m
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 06/08/2017.
6 | //
7 | //
8 |
9 | #import "NSString+RJBadge.h"
10 |
11 | @implementation NSString (RJBadge)
12 |
13 | #pragma mark - public
14 | + (NSString *)badgeFilePath
15 | {
16 | NSString *mpath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support"];
17 | NSString *bpath = [mpath stringByAppendingPathComponent:@"RJBadge"];
18 |
19 | NSURL *url = [NSURL fileURLWithPath:bpath];
20 | [self addSkipBackupAttributeToItemAtURL:url];
21 |
22 | return bpath;
23 | }
24 |
25 | + (NSString *)badgeJSONPath
26 | {
27 | NSFileManager *fileManager = [NSFileManager defaultManager];
28 | NSString *filePath = [self badgeFilePath];
29 |
30 | if (![fileManager fileExistsAtPath:filePath]) {
31 | [fileManager createDirectoryAtPath:filePath
32 | withIntermediateDirectories:YES
33 | attributes:nil error:nil];
34 | }
35 | return [filePath stringByAppendingPathComponent:@"badge.json"];
36 | }
37 |
38 | #pragma mark - private method
39 | + (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL *)URL
40 | {
41 | if ([[NSFileManager defaultManager] fileExistsAtPath:[URL path]]) {
42 | NSError *error = nil;
43 | BOOL success = [URL setResourceValue:[NSNumber numberWithBool:YES]
44 | forKey:NSURLIsExcludedFromBackupKey
45 | error:&error];
46 | if (!success) {
47 | NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent],
48 | error);
49 | }
50 | return success;
51 | }
52 | return NO;
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/RJBadgeKit/Classes/RJBadgeKit.h:
--------------------------------------------------------------------------------
1 | //
2 | // RJBadgeKit.h
3 | // RJBadgeKit
4 | //
5 | // Created by Ryan Jin on 04/08/2017.
6 | //
7 | //
8 |
9 | #ifndef RJBadgeKit_h
10 | #define RJBadgeKit_h
11 |
12 | #import "RJBadgeController.h"
13 | #import "NSObject+RJBadgeController.h"
14 | #import "UIBarButtonItem+RJBadge.h"
15 | #import "UITabBarItem+RJBadge.h"
16 | #import "UIView+RJBadge.h"
17 |
18 | #endif /* RJBadgeKit_h */
19 |
--------------------------------------------------------------------------------
/_Pods.xcodeproj:
--------------------------------------------------------------------------------
1 | Example/Pods/Pods.xcodeproj
--------------------------------------------------------------------------------