Blog about iOS development. Code snippets, best practice, discussions, stories, jokes and tutorials - everything that I can't post on Stackoverflow.
Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts
Friday, February 9, 2018
Saturday, February 3, 2018
Changing view's type on the Storyboard
Suppose the design of your app changed, and now you need to replace the Table View with a Collection View keeping all the constraints along with views hierarchy.
Drop a new View Controller on the storyboard and put a Collection View inside. Rename it in the left panel (called Document Outline). Name it "The Replacement" so you will be able recognize it later. Now switch to the Source Code through the Open As. Now the storyboard looks like XML markup. Find the Table View you need to replace, it will be scoped within the tableView tag.
Copy its id (example: id="8Oa-xL-ums"). It points to the view in constraints and outlets. Now find the new Collection View under the collectionView tag.
Copy everything including the enclosing tags:
<collectionView ...</collectionView>
and paste it instead of the tableView. Replace Collection View's id with the value you copied from the Table View. Before switching back to Interface Builder you need to clean up the storyboard. Remove the scene of the temporary View Controller that you created at the beginning of the tutorial. Delete everything between tags and the preceding comment: <!--View Controller>
<scene ...</scene>
. If you don't do this you will have an error because of duplicated id.
Now you will have the new Collection View constrained like the Table View but misplaced, because it's was copied with the rect. Click Update Frames and enjoy the result!
Here is the list of storyboard tags for different UI classes. Who knows, may be it will be useful.
arscnView | ARSCNView |
arskView | ARSKView |
glkView | GLKView |
mapView | MKMapView |
mtkView | MTKView |
sceneKitView | SCNView |
skView | SKView |
activityIndicatorView | UIActivityIndicatorView |
button | UIButton |
collectionView | UICollectionView |
datePicker | UIDatePicker |
imageView | UIImageView |
label | UILabel |
navigationBar | UINavigationBar |
pageControl | UIPageControl |
pickerView | UIPickerView |
progressView | UIProgressView |
scrollView | UIScrollView |
searchBar | UISearchBar |
segmentedControl | UISegmentedControl |
slider | UISlider |
stackView | UIStackView |
stepper | UIStepper |
switch | UISwitch |
tabBar | UITabBar |
tableView | UITableView |
textField | UITextField |
textView | UITextView |
toolbar | UIToolbar |
view | UIView |
containerView | UIView (with embedded View Controller) |
visualEffectView | UIVisualEffectView |
webView | UIWebView |
wkWebView | WKWebView |
Friday, January 19, 2018
Safer parsing with JSONSerialization in Swift
Github gist.
Most people use the following snippet to get a value from an object provided by the JSONSerialization:
It's not obvious, but this code is unsafe. It can easily fail if the "name" value will be "111". In this case it may be decoded as
I didn't find any tutorial that would take this issue into account. All of them recommend to use
All objects produced by
Most people use the following snippet to get a value from an object provided by the JSONSerialization:
guard let name = jsonDictionary["name"] as? String else { return }
...
It's not obvious, but this code is unsafe. It can easily fail if the "name" value will be "111". In this case it may be decoded as
NSNumber
and casting to String
will always fail. The same thing with numbers: guard let id = jsonDictionary["id"] as? Int else { return }
// id can be a "3" String!
...
A value like "3" can be decoded both as NSString
and NSNumber
(more often).I didn't find any tutorial that would take this issue into account. All of them recommend to use
as?
to unknown JSON object to basic type. So I post here the correct snippets that will provide stable and predictable results in all possible cases.JSON helpers
extension String {
init?(jsonObject: Any?) {
guard jsonObject is NSNull == false else { return nil }
let aNSObject = jsonObject as? NSObject
if let description = aNSObject?.description {
self = description
} else {
return nil
}
}
}
extension Int {
var boolValue: Bool { return self != 0 }
init?(jsonObject: Any?) {
if let number = jsonObject as? NSNumber {
self = number.intValue
} else if let string = jsonObject as? NSString {
self = string.integerValue
} else {
return nil
}
}
}
extension Bool {
init?(jsonObject: Any?) {
if let integer = Int(jsonObject: jsonObject) {
self = integer.boolValue
} else {
return nil
}
}
}
extension Double {
init?(jsonObject: Any?) {
if let number = jsonObject as? NSNumber {
self = number.doubleValue
} else if let string = jsonObject as? NSString {
self = string.doubleValue
} else {
return nil
}
}
}
All objects produced by
JSONSerialization
are instances of NSString
, NSNumber
, NSArray
, NSDictionary
, or NSNull
.
Subscribe to:
Posts (Atom)