-
-
Save byJeevan/9b72128ed97a1dd80a389d683739b6f4 to your computer and use it in GitHub Desktop.
Swift iOS Code Recipes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Swift iOS Recipes | |
================== | |
> https://github.com/JohnSundell/SwiftTips | |
** GUI Layout ** | |
//Avoid Table view having Textfield covered by Keyboard | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil) | |
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil) | |
view.endEditing(true) | |
} | |
@objc func keyboardWillShow(_ notification: Notification) { | |
let keyboardSize: CGSize? = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue?.size | |
let animationDuration = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]) as? CGFloat | |
UIView.animate(withDuration: TimeInterval(animationDuration!), animations: {() -> Void in | |
self.tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize?.height)!, 0.0) | |
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize?.height)!, 0.0) | |
}) | |
} | |
@objc func keyboardWillHide(_ notification: Notification) { | |
let animationDuration = (notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]) as? CGFloat | |
UIView.animate(withDuration: TimeInterval(animationDuration!), animations: {() -> Void in | |
self.tableView.contentInset = UIEdgeInsets.zero | |
self.tableView.scrollIndicatorInsets = UIEdgeInsets.zero | |
}) | |
} | |
override func viewWillDisappear(_ animated: Bool) { | |
super.viewWillDisappear(animated) | |
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil) | |
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) | |
} | |
///End/// | |
//DismissView - when dialog kind of presented and tapped out side of box. Target view usually the container/parent view of dialog. | |
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { | |
if let touch = touches.first, !<target view>.bounds.contains(touch.location(in: <target view>)) { | |
//do dismissal call | |
} | |
} | |
//Keyboard shows over textfield when dialog appears | |
//in viewDidLoad | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) | |
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) | |
//Add these selectors | |
@objc func keyboardWillShow(notification: NSNotification) { | |
if !isKeyboardAppear { | |
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { | |
if self.view.frame.origin.y == 0{ | |
self.view.frame.origin.y -= keyboardSize.height | |
} | |
} | |
isKeyboardAppear = true | |
} | |
} | |
@objc func keyboardWillHide(notification: NSNotification) { | |
if isKeyboardAppear { | |
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { | |
if self.view.frame.origin.y != 0{ | |
self.view.frame.origin.y += keyboardSize.height | |
} | |
} | |
isKeyboardAppear = false | |
} | |
} | |
//Alerts | |
var alert = UIAlertController(title: "Alert", message: "Message", preferredStyle: UIAlertControllerStyle.Alert) | |
alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil)) | |
self.presentViewController(alert, animated: true, completion: nil) | |
//Buttons on navigation | |
let newButton = UIBarButtonItem(barButtonSystemItem: .Edit, target: self, action: "doSomething:") | |
self.navigationItem.leftBarButtonItem = newButton | |
### Print as JSON by given Dictionary or [AnyHashable:Any] | |
``` | |
if let theJSONData = try? JSONSerialization.data( | |
withJSONObject: <Your Dictionary>, | |
options: [.prettyPrinted]) { | |
let theJSONText = String(data: theJSONData, | |
encoding: .ascii) | |
print("JSON string = \(theJSONText!)") | |
} | |
``` | |
### for Objective-C : | |
``` | |
NSError *jerror; | |
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseData | |
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string | |
error:&jerror]; | |
if (! jsonData) { | |
NSLog(@"Got an error: %@", jerror); | |
} else { | |
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; | |
NSLog(@"JSON >> %@", jsonString); | |
} | |
``` | |
// Table View inside Table View Cell issue | |
// - Outer cell will not expand as per inner table view height. | |
// PS: Make InnerTableView scrolling false. | |
class InnerTableView: UITableView { | |
override var intrinsicContentSize: CGSize { | |
self.layoutIfNeeded() | |
return self.contentSize | |
} | |
override var contentSize: CGSize { | |
didSet{ | |
self.invalidateIntrinsicContentSize() | |
} | |
} | |
} | |
// Button Quick for test | |
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton | |
button.frame = CGRectMake(100, 100, 100, 50) | |
button.backgroundColor = UIColor.greenColor() | |
button.setTitle("Test Button", forState: UIControlState.Normal) | |
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside) | |
button.layer.cornerRadius = 5 | |
button.layer.borderWidth = 1 | |
button.layer.borderColor = UIColor.blackColor().CGColor | |
self.view.addSubview(button) | |
func buttonAction(sender:UIButton!) { | |
//do something | |
} | |
// Quick Label creation for test | |
newLabel = UILabel(frame: CGRect(x: 20, y: 10, width: 300, height: 200)) | |
newLabel.text = "Tap and hold for settings" | |
newLabel.textColor = UIColor.whiteColor() | |
newLabel.textAlignment = NSTextAlignment.Center | |
newLabel.font = UIFont(name: "HelveticaNeue", size: CGFloat(17)) | |
// Slider | |
var slider = UISlider(frame: CGRectMake(0, 0, 300, 200)) | |
slider.addTarget(self, action: "changeSomething:", forControlEvents: UIControlEvents.ValueChanged) | |
slider.backgroundColor = UIColor.blackColor() | |
slider.minimumValue = 0.0 | |
slider.maximumValue = 1.0 | |
slider.continuous = true | |
slider.value = 0.5 | |
self.view.addSubview(slider) | |
func changeSomething(sender:UISlider!) { | |
self.someValue = sender.value | |
} | |
//Dimensions | |
var screenSize: CGRect = UIScreen.mainScreen().bounds | |
//Collection View | |
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() | |
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) | |
layout.itemSize = CGSize(width: 120, height: 90) | |
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout) | |
collectionView!.dataSource = self | |
collectionView!.delegate = self | |
collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) | |
collectionView!.backgroundColor = UIColor.blackColor() | |
self.view.addSubview(collectionView!) | |
//Table View | |
tableView = UITableView(frame: self.view.frame, style: .Plain) | |
self.view.addSubview(tableView) | |
tableView.delegate = self | |
tableView.dataSource = self | |
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier) | |
//Image View | |
var frame = self.view.frame | |
someImage = UIImageView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)) | |
//Transitions | |
Pushes | |
let vc = SettingsViewController() | |
self.navigationController?.pushViewController(vc, animated: true) | |
Segues (have to use IB to set up segue identifiers) | |
//Constraints with Masonry Snap | |
let padding = UIEdgeInsetsMake(10, 10, 10, -50) | |
let superview = self.view | |
someView.snp_makeConstraints { make in | |
make.top.equalTo(superview.snp_top).with.offset(padding.top) | |
make.left.equalTo(superview.snp_left).with.offset(padding.left) | |
} | |
/** GUI Events ** | |
//Gray Activity Indicator View | |
var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .Gray) | |
view.addSubview(activityIndicatorView) | |
activityIndicatorView.center = view.center | |
activityIndicatorView.startAnimating() | |
activityIndicatorView.removeFromSuperview() | |
//Touches | |
press = UILongPressGestureRecognizer(target: self, action: "doSomething:") | |
press.minimumPressDuration = 0.5 | |
press.numberOfTapsRequired = 0 | |
press.numberOfTouchesRequired = 1 | |
press.delegate = self | |
self.view.addGestureRecognizer(press) | |
//Notifications | |
NSNotificationCenter.defaultCenter().addObserver( | |
self, | |
selector: "doSomething:", | |
name: someKey, | |
object: nil) | |
func doSomething(notification: NSNotification) { | |
} | |
//App Delegate setup | |
let rootViewController = SomeViewController() | |
let frame = UIScreen.mainScreen().bounds | |
self.window = UIWindow(frame: frame) | |
let navController = UINavigationController(rootViewController: rootViewController) | |
self.window?.rootViewController = navController | |
self.window?.backgroundColor = UIColor.whiteColor() | |
self.window?.makeKeyAndVisible() | |
//Delegates | |
protocol NewDelegate { | |
func doSomething() | |
} | |
In class: | |
var delegate: NewDelegate? | |
self.delegate?.doSomething() | |
In target class: | |
Inherit from NewDelegate | |
newObject.delegate = self | |
Implement the protocol methods | |
// ****** Loads Xib/nib from project as uiviewcontroller ****/ | |
extension UIViewController { | |
static func loadFromNib() -> Self { | |
func instantiateFromNib<T: UIViewController>() -> T { | |
return T.init(nibName: String(describing: T.self), bundle: nil) | |
} | |
return instantiateFromNib() | |
} | |
} | |
/*****Loads ViewController by all ways : ***/ | |
extension UIViewController { | |
static func instantiate<TController: UIViewController>(_ storyboardName: String) -> TController { | |
return instantiateFromStoryboardHelper(storyboardName) | |
} | |
static func instantiate<TController: UIViewController>(_ storyboardName: String, identifier: String) -> TController { | |
return instantiateFromStoryboardHelper(storyboardName, identifier: identifier) | |
} | |
fileprivate static func instantiateFromStoryboardHelper<T: UIViewController>(_ name: String, identifier: String? = nil) -> T { | |
let storyboard = UIStoryboard(name: name, bundle: Bundle(for: self)) | |
return storyboard.instantiateViewController(withIdentifier: identifier ?? String(describing: self)) as! T | |
} | |
static func instantiate<TController: UIViewController>(xibName: String? = nil) -> TController { | |
return TController(nibName: xibName ?? String(describing: self), bundle: Bundle(for: self)) | |
} | |
} | |
/ ***** End Load a ViewController ***** / | |
extension String { | |
func replaceOccuranceOfSpaceInURLString() -> String { | |
return self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? self | |
} | |
var boolValue: Bool { | |
return (self as NSString).boolValue | |
} | |
var isBackSpace:Bool { | |
let char = self.cString(using: String.Encoding.utf8)! | |
let isBackSpace = strcmp(char, "\\b") | |
return isBackSpace == -92 | |
} | |
} | |
// Storing a property in a class using Static property. | |
extension UIView { | |
struct Holder { | |
static var _padding:[UIView:UIEdgeInsets] = [:] | |
} | |
var padding : UIEdgeInsets { | |
get{ return UIView.Holder._padding[self] ?? .zero} | |
set { UIView.Holder._padding[self] = newValue } | |
} | |
} | |
//Button Extension that makes button with icon at top | |
// -----[image]----------- | |
// ----title of button---- | |
// ----------------------- | |
extension UIButton { | |
func centerVertically(padding: CGFloat = 6.0) { | |
guard | |
let imageViewSize = self.imageView?.frame.size, | |
let titleLabelSize = self.titleLabel?.frame.size else { | |
return | |
} | |
let totalHeight = self.bounds.size.height | |
self.imageEdgeInsets = UIEdgeInsets( | |
top: max(0, -(totalHeight - imageViewSize.height)), | |
left: 0.0, | |
bottom: 0.0, | |
right: -titleLabelSize.width | |
) | |
self.titleEdgeInsets = UIEdgeInsets( | |
top: 0.0, | |
left: -imageViewSize.width, | |
bottom: -(totalHeight - titleLabelSize.height), | |
right: 0.0 | |
) | |
self.contentEdgeInsets = UIEdgeInsets( | |
top: 0.0, | |
left: 0.0, | |
bottom: titleLabelSize.height, | |
right: 0.0 | |
) | |
} | |
} | |
//Extension - shortcut to add child vc | |
extension UIViewController { | |
func add(_ child: UIViewController) { | |
addChild(child) | |
view.addSubview(child.view) | |
child.didMove(toParent: self) | |
} | |
func remove() { | |
// Just to be safe, we check that this view controller | |
// is actually added to a parent before removing it. | |
guard parent != nil else { | |
return | |
} | |
willMove(toParent: nil) | |
view.removeFromSuperview() | |
removeFromParent() | |
} | |
} | |
Author
byJeevan
commented
Dec 2, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment