Reputation: 979
I have a part in my app in which users can take a quick photo and save it to the camera roll. My only is that after the photo has been taken, it comes to the screen with the square cropper (i guess that's what it is) and then down the bottom it says "Retake" and "Use Photo". I want that Use Photo to say "Save Photo" (which is what it does anyway). Is there anyway to do this? Here's my code
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
UIImageWriteToSavedPhotosAlbum(chosenImage, nil, nil, nil);
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
Upvotes: 1
Views: 2245
Reputation: 2388
private func swizzle(_ bundle: Bundle.Type) {
[(#selector(bundle.localizedString(forKey:value:table:)),
#selector(bundle.rd_localizedString(forKey:value:table:)))]
.forEach { original, swizzled in
guard let originalMethod = class_getInstanceMethod(bundle, original),
let swizzledMethod = class_getInstanceMethod(bundle, swizzled) else { return }
let didAddMethod = class_addMethod(
bundle,
original,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)
)
if didAddMethod {
class_replaceMethod(
bundle,
swizzled,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod)
)
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
private var hasSwizzled = false
extension Bundle {
final public class func
doBadSwizzleStuff() {
guard !hasSwizzled else { return }
hasSwizzled = true
swizzle(self)
}
@objc internal func rd_localizedString(forKey: String, value: String?, table: String?) -> String {
let bundle = Bundle.main
return bundle.rd_localizedString(forKey: forKey, value: value, table: table)
}
}
Below content of mentioned files with keys I've seen (with standard english values), they are pretty self explaining
"PHOTO" = "PHOTO";
"AEAF_LOCK_TEXT" = "AE/AF LOCK";
"API_CANCEL_TITLE" = "Cancel";
"HDR_AUTO" = "Auto";
"HDR_ON" = "On";
"HDR_OFF" = "Off";
"TIMER_OFF_TEXT" = "Off";
"USE_PHOTO" = "Use Photo";
"PHOTOS" = "Photos";
"CAMERA_ROLL" = "Camera roll";
"ALL_SCREENSHOTS" = "Screenshots";
"CANCEL" = "Cancel";
"RETAKE" = "Retake";
"STREAM_SHARED_BY_ME_SUBTITLE" = "From You";
"STREAM_SHARED_BY_SUBTITLE" = "From %@";
"ALBUM_IMAGE_COUNT_FORMAT" = "%@ Photos";
"ALBUM_VIDEO_COUNT_FORMAT" = "%@ Videos";
"1_ALBUM_PHOTO" = "1 Photo";
"1_ALBUM_VIDEO" = "1 Video";
"ALBUM_TWO_TYPES_LABEL_COMMAS" = "%@, %@";
"ALL_PHOTOS_IN_LIBRARY" = "Moments";
"PXUserCollectionsSectionTitle" = "My Albums";
"FULL_PHOTOS_GRID_ZOOM_LEVEL_TITLE" = "Moments";
"NO_PHOTOS_OR_VIDEOS" = "No Photos or Videos";
internal enum L10n {
internal enum CameraUI {
/// AE/AF LOCK
internal static let aeafLockText = L10n.tr("CameraUI", "AEAF_LOCK_TEXT")
/// Cancel
internal static let apiCancelTitle = L10n.tr("CameraUI", "API_CANCEL_TITLE")
/// Auto
internal static let hdrAuto = L10n.tr("CameraUI", "HDR_AUTO")
/// Off
internal static let hdrOff = L10n.tr("CameraUI", "HDR_OFF")
/// On
internal static let hdrOn = L10n.tr("CameraUI", "HDR_ON")
/// PHOTO
internal static let photo = L10n.tr("CameraUI", "PHOTO")
/// Off
internal static let timerOffText = L10n.tr("CameraUI", "TIMER_OFF_TEXT")
/// Use test
internal static let usePhoto = L10n.tr("CameraUI", "USE_PHOTO")
}
// MARK: - Implementation Details
extension L10n {
private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
// swiftlint:disable:next nslocalizedstring_key
let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "")
return String(format: format, locale: Locale.current, arguments: args)
}
}
private final class BundleToken {}
Upvotes: 0
Reputation: 1
you can find this with recusrion way
func buttonWithTitle(forView view: UIView, title: String) -> UIButton? {
guard view.subviews.count > 0 else { return nil }
var needButton: UIButton? = nil
for subview in view.subviews {
if subview is UIButton {
let button = subview as! UIButton
if button.titleLabel?.text == title {
return button
}
}
needButton = buttonWithTitle(forView: subview, title: title)
if needButton != nil { return needButton }
}
return needButton
}
Upvotes: 0
Reputation: 1062
U can change cancel button to any title u want:
Add the below codes in your viewController:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self changeCancelToAnythingUWantOf:viewController andReplacementString:@"Your Replacement String"];
}
- (void)changeCancelToAnythingUWantOf:(UIViewController*)vc andReplacementString:(NSString*)title {
for(UIView *subView in vc.view.subviews) {
if ([subView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)subView;
if([btn.titleLabel.text isEqualToString:@"Cancel"]) {
[btn setTitle:title forState:UIControlStateNormal];
break;
}
}
if (subView.subviews) {
for (UIView *subSubView in subView.subviews) {
if ([subSubView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)subSubView;
if([btn.titleLabel.text isEqualToString:@"Cancel"]) {
[btn setTitle:title forState:UIControlStateNormal];
break;
}
}
if (subSubView.subviews) {
for (UIView *subSubSubView in subSubView.subviews) {
if ([subSubSubView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)subSubSubView;
if([btn.titleLabel.text isEqualToString:@"Cancel"]) {
[btn setTitle:title forState:UIControlStateNormal];
break;
}
}
}
}
}
}
}
}
Upvotes: 3