Skip to content

Commit

Permalink
Merge branch 'sdcalertcontroller'
Browse files Browse the repository at this point in the history
Conflicts:
	SDCAlertView.podspec
	SDCAlertView.xcodeproj/project.pbxproj
  • Loading branch information
sberrevoets committed Oct 16, 2014
2 parents 223151e + e40349c commit 18d623c
Show file tree
Hide file tree
Showing 50 changed files with 2,737 additions and 745 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# CHANGELOG

# 2.0

**What's New:**
- All new API that matches and extends `UIAlertController`
- Ability to always show buttons horizontally or vertically
- Backwards compatible with `SDCAlertView` (1.0)
- More stylistic elements you can style (alert width, button separators, text fields, etc.)

## 1.4.3

**Bug Fixes:**
- Fixes an issue that would not enforce `contentPadding` on the title and message labels properly (#58)

## 1.4.2

**What's New:**
- Extra properties to specify padding and spacing in the alert (#55 - thanks @bcherry)

## 1.4.1

**Bug Fixes:**
Expand Down
154 changes: 69 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,138 +1,123 @@
#SDCAlertView
# SDCAlertView

`SDCAlertView` doesn't just look like a system alert in terms of user interface elements, it is the result of completely reverse-engineering `UIAlertView`. View hierarchy, labels, buttons, animations, user interaction; everything has been looked at and incorporated as much as possible.

You can think of `SDCAlertView` as `UIAlertView` on steroids. It has added functionality such as a `contentView` property and block syntax, while still keeping the `UIAlertView` look.

![Animated GIF showing alert](http://sberrevoets.github.io/SDCAlertView/ProgressViewAlert.gif)
## iOS 8 & `UIAlertController`
In iOS 8, `UIAlertView` was deprecated in favor of `UIAlertController`. `SDCAlertView` was also updated to include `SDCAlertController`, whose API matches its `UI` counterpart.

But that wasn't all, the entire view hierarchy changed again and even the way of presenting the alert changed. Fortunately, the new implementation was a lot easier to copy, though some sacrifices had to be made in terms of likeness. The culprits, two private classes by the name of `_UIBackdropView` and `_UIBlendingHighlightView`, were used quite a bit, and although `UIVisualEffectView` comes close to making it look exactly right, there are differences.

Ignoring minor differences (that you would really only see if you looked for them), everything that was possible in `SDCAlertView` is also possible in `SDCAlertController`, though probably in the form of a new API. `SDCAlertController` is backwards compatible with `SDCAlertView`, meaning you can replace your existing `SDCAlertView` instances with `SDCAlertController` instances, even if your deployment target is iOS 7.

**This means that you should rarely use `SDCAlertView` anymore. Consider it, just like `UIAlertView`, deprecated and only use `SDCAlertController` moving forward. If you want to keep using `SDCAlertView` because it has functionality `SDCAlertController` does not, open an issue. This is considered a bug.**

## Installation
The easiest way to install is, of course, by using CocoaPods. The name of the pod is `SDCAlertView`.

If you're not using CocoaPods, you need:
If you're not using CocoaPods, you need all classes in the [Source](https://github.com/sberrevoets/SDCAlertView/tree/master/SDCAlertView/Source) directory.

- SDCAlertView.{h,m}
- SDCAlertViewTransitioning.h
- SDCAlertViewCoordinator.{h,m}
- SDCAlertViewController.{h,m}
- SDCAlertViewContentView.{h,m}
- SDCAlertViewBackgroundView.{h,m}
- SDCIntrinsicallySizedView.{h,m}

The project also depends on [RBBAnimation](https://github.com/robb/RBBAnimation) and [SDCAutoLayout](https://github.com/Scott90/SDCAutoLayout). These dependencies are automatically handled for you if you use CocoaPods.
The project also depends on [RBBAnimation](https://github.com/robb/RBBAnimation) (`SDCAlertView` only) and [SDCAutoLayout](https://github.com/sberrevoets/SDCAutoLayout). These dependencies are automatically handled for you if you use CocoaPods.

## Usage
`SDCAlertView` is for use in iOS 7 only. It will not work properly on iOS 6.1 or below. Using `SDCAlertView` is very simple: just import SDCAlertView.h and use it as you would `UIAlertView`.
`SDCAlertController` is for use in iOS 7 or higher only. It will not work properly on iOS 6.1 or below. Using the library is very simple: just import SDCAlertController.h and use it as you would `UIAlertController`.

### Basic

Showing a basic `SDCAlertView` alert looks just like showing a basic `UIAlertView` alert:
Showing a basic `SDCAlertController` alert looks just like showing a basic `UIAlertController` alert:
```objc
SDCAlertView *alert = [[SDCAlertView alloc] initWithTitle:@"Title"
message:@"This is a message"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
[alert show];
SDCAlertController *alert = [SDCAlertController alertControllerWithTitle:@"Title"
message:@"This is a message"
preferredStyle:SDCAlertControllerStyleAlert];
[alert addAction:[SDCAlertAction actionWithTitle:@"OK" style:SDCAlertActionStyleDefault handler:nil]];
[alert presentWithCompletion:nil];
```
Or you can use one of the convenience methods:
```objc
[SDCAlertView alertWithTitle:@"Title" message:@"This is a message" buttons:@[@"OK"]];
```

### Block syntax

Block syntax saves you from having to use a delegate:
```objc
SDCAlertView *alert = [[SDCAlertView alloc] initWithTitle:@"Title"
message:@"This is a message"
delegate:nil
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
[alert showWithDismissHandler:^(NSInteger buttonIndex) {
NSLog(@"Tapped button: %@", @(buttonIndex));
}];
[SDCAlertController showAlertControllerWithTitle:@"Title" message:@"This is a message" actionTitle:@"OK"]
```

### `contentView`

Of course, you're not using `SDCAlertView`'s full potential unless you are using the `contentView`:
```objc
SDCAlertView *alert = [[SDCAlertView alloc] initWithTitle:@"Title"
message:@"This is a message"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"OK", nil];
SDCAlertController *alert = [SDCAlertController alertControllerWithTitle:@"Title"
message:@"This is a message"
preferredStyle:SDCAlertControllerStyleAlert];
[alert addAction:[SDCAlertAction actionWithTitle:@"OK" style:SDCAlertActionStyleDefault handler:nil]];

UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] init];
spinner.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[spinner setTranslatesAutoresizingMaskIntoConstraints:NO];
[spinner startAnimating];

[alert.contentView addSubview:spinner];
[spinner sdc_horizontallyCenterInSuperview];
[spinner sdc_verticallyCenterInSuperviewWithOffset:SDCAutoLayoutStandardSiblingDistance];
[alert show];
[alert.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[spinner]-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(spinner)]];

[alert presentWithCompletion:nil];
```
### Additional delegate methods
### Dismissal Prevention
You can use the `shouldDismissBlock` to prevent an alert from being dismissed:
You can also use the `alertView:shouldDismissWithButtonIndex:` and `alertView:shouldDeselectButtonAtIndex:` to prevent an alert from dismissing:
```objc
- (void)showAlert {
SDCAlertView *alert = [[SDCAlertView alloc] initWithTitle:title
message:message
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:nil];
[alert show];
}
SDCAlertController *alert = [SDCAlertController alertControllerWithTitle:@"Title"
message:@"This is a message"
preferredStyle:SDCAlertControllerStyleAlert];
[alert addAction:[SDCAlertAction actionWithTitle:@"OK" style:SDCAlertActionStyleDefault handler:nil]];
- (BOOL)alertView:(SDCAlertView *)alertView shouldDismissWithButtonIndex:(NSInteger)buttonIndex {
alert.shouldDismissBlock = ^ BOOL(SDCAlertAction *action) {
return NO;
}
};
- (BOOL)alertView:(SDCAlertView *)alertView shouldDeselectButtonAtIndex:(NSInteger)buttonIndex {
return YES;
}
[alert presentWithCompletion:nil];
```
This will deselect the cancel button when it's tapped, but it won't actually dismiss the alert. Useful for password-like alerts that you don't want dismissed until the right password is entered.

### Styling and appearance
### Styling and Appearance

`SDCAlertController` is a normal view controller, so applying a `tintColor` to its `view` will color the buttons and any subviews you add to the `contentView`. If you are looking for more customizations, create a class that conforms to the `SDCAlertControllerVisualStyle` protocol and set it as the `visualStyle` on an `SDCAlertController` instance. You can also subclass `SDCAlertControllerDefaultVisualStyle` for a set of default values that you can then override as needed.

If you're feeling particularly adventurous, you can use a different transition/animation by creating a class that conforms to `UIViewControllerTransitioningDelegate` and setting it as the alert's `transitionCoordinator`. Transitioning is implemented using default iOS 8 custom view controller transitions, so anything you can do with a normal view controller, you can do with an alert controller.

## Backwards compatibility

`SDCAlertController` will in most cases be backwards compatible with `SDCAlertView`. However, most is not all, and if you need to fine-tune an alert just for iOS 7, you can still do that:

`SDCAlertView` uses the `tintColor` for buttons and any subviews you add to the `contentView`. If you are looking for more customizations, you can use `UIAppearance` to style alerts (per instance or all at once):
```objc
[[SDCAlertView appearance] setTitleLabelFont:[UIFont boldSystemFontOfSize:22]];
[[SDCAlertView appearance] setMessageLabelFont:[UIFont italicSystemFontOfSize:14]];
[[SDCAlertView appearance] setNormalButtonFont:[UIFont boldSystemFontOfSize:12]];
[[SDCAlertView appearance] setSuggestedButtonFont:[UIFont italicSystemFontOfSize:12]];
[[SDCAlertView appearance] setTextFieldFont:[UIFont italicSystemFontOfSize:12]];
[[SDCAlertView appearance] setButtonTextColor:[UIColor grayColor]]; // will always override the tintColor
[[SDCAlertView appearance] setTextFieldTextColor:[UIColor purpleColor]];
[[SDCAlertView appearance] setTitleLabelTextColor:[UIColor greenColor]];
[[SDCAlertView appearance] setMessageLabelTextColor:[UIColor yellowColor]];
SDCAlertController *alert = [SDCAlertController alertWithTitle:@"Title" message:@"Message" preferredStyle:SDCAlertControllerStyleAlert];
// ... configure alert with content view, text fields, buttons, etc ...

if (alert.legacyAlertView) {
// ... use alert.legacyAlertView to make iOS 7 modifications
} else {
// Keep using original alert
}

[alert presentWithCompletion:nil];
```
If you're feeling particularly adventurous, `SDCAlertView` makes it very easy to customize the way alerts are presented and dismissed. Set the `transitionCoordinator` property to a custom class that conforms to `SDCAlertViewTransitioning`, and implement the three protocol methods. For more detailed instructions, see SDCAlertViewTransitioning.h.
## Behavior different from `UIAlertController`
## Behavior different from `UIAlertView`
Unfortunately, there are a few things that can't or won't be duplicated:
With the introduction of `SDCAlertController`, pretty much all behavior in alerts could be replicated. If you use the legacy `SDCAlertView`, you may run into some additional problems as described below:
- Special interaction with the system. The system does not consider instances of `SDCAlertView` actual alerts, which means that, for example, the `alertViewCancel:` method from `SDCAlertViewDelegate` will never be called.
- `UITextField` placeholders in different languages. "Login" and "Password" are entered as localized strings, but they aren't actually translated.
- Some behavior is purposely not ported from `UIAlertView`. These cases are discussed in SDCAlertView.h.
- Special interaction with the system. The system does not consider instances of `SDCAlertController` actual alerts, which means that won't experience the normal system interaction you'd expect from a normal alert. This also means that combining `SDCAlertView` with `SDCAlertController` is a **bad idea**.
- **`SDCAlertView` only:** `UITextField` placeholders in different languages. "Login" and "Password" are entered as localized strings, but they aren't actually translated.
- **`SDCAlertView` only:** Some behavior is purposely not ported from `UIAlertView`. These cases are discussed in SDCAlertView.h.
## New in 1.4
## New in 2.0
**What's New:**
- Added the ability to position a two-button alert vertically as opposed to horizontally
- Added `attributedTitle` and `attributedMessage` properties
**Bug Fixes:**
- Auto-layout doesn't complain anymore when using `[[SDCAlertView alloc] init]`
- Fixes a bug that would not show correct button titles in certain alert configurations
- Instead of clipping button text, it now reduces the size of text on buttons appropriately
- All new API that matches and extends `UIAlertController`
- Ability to always show buttons horizontally or vertically
- Backwards compatible with `SDCAlertView` (1.0)
- More stylistic elements you can style (alert width, button separators, text fields, etc.)
## Support
I'm pretty active on [Stack Overflow](http://stackoverflow.com/users/751268/scott-berrevoets), so please use that if you have any questions. You can also use [Twitter](http://twitter.com/ScottBerrevoets) to contact me directly.
Expand All @@ -144,6 +129,5 @@ Some credits are in order:
- Robert Böhnke ([@robb](https://github.com/robb)): [RBBAnimation](https://github.com/robb/RBBAnimation)
- Lee McDermott ([@lmcd](https://github.com/lmcd)) for reverse-engineering the showing and dismissing animations.
- César Castillo ([@JagCesar](https://github.com/JagCesar)) for the great idea of using a `UIToolbar` for easy live blurring (used in earlier versions of SDCAlertView).
And everyone else who contributed by reporting issues, creating pull requests, or in some other way!
2 changes: 1 addition & 1 deletion SDCAlertView.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'SDCAlertView'
s.version = '1.4.3'
s.version = '2.0'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.authors = { 'Scott Berrevoets' => '[email protected]' }
s.summary = 'SDCAlertView is a UIAlertView clone with added functionality including a contentView property'
Expand Down
Loading

0 comments on commit 18d623c

Please sign in to comment.