Apple just announced SwiftUI today.
SwiftUI will be used to declare the user interface and behavior for your app on every platform.
Here are some basic resources to understand SwiftUI:
Apple Documentation
Tutorials for SwiftUI
Sample from WWDC 2019 Event:
Hope it will help you to look into it.
Happy Coding 🙂
iOS
Take advantage of raw strings in Swift 5
Swift 5 comes with enhancement in string literals delimiters to support Raw Text.
Little snippet to know if application is installed via TestFlight
I found little snippet from twitter about how to know if application is installed via TestFlight.
Here, appStoreReceiptURL
is an instance property, which we can find from main bundle.
Here, I am adding snippet for both Objective-C and Swift.
Warnings and Errors while upgrading from Swift 4.x to Swift 4.2 in Xcode 10.0
Following are warnings and errors will come while upgrading from Swift 4.x to Swift 4.2 in Xcode 10.0
Tutorial : Let's take quick dive in Grouped Notifications - iOS 12
With iOS 12 we can set the group of notifications
Thread Identifier
Create notification content with threadIdentifier
to create group of that notification. Group will be of the application or specific topic from an application.
1 2 3 4 5 |
// Creating Groups with Thread Identifiers let content = UNMutableNotificationContent() content.title = "Notifications Group" content.body = "Tutorial by Ashish Kakkad" content.threadIdentifier = "notify-team-ios" |
Notification payload will be like this
1 2 3 4 5 6 7 8 9 |
{ "aps" : { "alert" : { "title" : "Notifications Group", "body" : "Tutorial by Ashish Kakkad" } "thread-id" : "notify-team-ios" } } |
Give meaningful name to thread identifier for specific purpose of group.
Summary of group
Simple Notification Group Summary
1 2 |
let summaryFormat = "%u more messages" return UNNotificationCategory(identifier: "category-identifier", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: nil, categorySummaryFormat: summaryFormat, options: []) |
Hidden Previews Summary Customization
1 2 3 |
let summaryFormat = "%u more messages" let hiddenPreviewsPlaceholder = "%u messages" return UNNotificationCategory(identifier: "category-identifier", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: hiddenPreviewsPlaceholder, categorySummaryFormat: summaryFormat, options: []) |
Notification Group Summary with Arguments
1 2 |
let summaryFormat = "%u more messages from %@" return UNNotificationCategory(identifier: "group-messages", actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: nil, categorySummaryFormat: summaryFormat, options: []) |
Notification Group Summary Argument
1 2 3 4 |
let content = UNMutableNotificationContent() content.body = "…" content.threadIdentifier = "notify-team-ios" content.summaryArgument = "Ashish" |
Notification Summary with Argument Count
1 2 3 4 5 |
let content = UNMutableNotificationContent() content.body = "…" content.threadIdentifier = "notify-team-ios" content.summaryArgument = "Ashish" content.summaryArgumentCount = 2 |
Updated notification payload will be like this
1 2 3 4 5 6 7 8 9 10 |
{ "aps" : { "alert" : { "body" : "…", "summary-arg" : "Ashish", "summary-arg-count" : 2 }, "thread-id" : "notify-team-ios" } } |
Example with local notifications:
Setup user notifications in the application.
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 29 30 31 32 33 34 35 36 |
// // AppDelegate.swift // AKGroupedNotifications // // Created by Ashish Kakkad on 21/06/18. // Copyright © 2018 Kode. All rights reserved. // import UIKit import UserNotifications @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. let center = UNUserNotificationCenter.current() center.delegate = self let options: UNAuthorizationOptions = [.alert, .sound] center.requestAuthorization(options: options) { (granted, error) in if !granted { print("Something went wrong") } } center.getNotificationSettings { (settings) in if settings.authorizationStatus != .authorized { // Notifications not allowed } } return true } } extension AppDelegate : UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) } } |
Fire local notifications and look into the thread identifier, summary and summary count…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
if #available(iOS 10.0, *) { for i in 1...5 { let content = UNMutableNotificationContent() content.categoryIdentifier = "AKNotification" content.title = "Notification \(i)" content.body = "\(Date())" if i == 2 { content.threadIdentifier = "ak-notingroup" } else { content.threadIdentifier = "ak-group-website" content.summaryArgumentCount = 1 content.summaryArgument = "by ashishkakkad.com" } let trigger = UNTimeIntervalNotificationTrigger(timeInterval: TimeInterval(10*i), repeats: false) let request = UNNotificationRequest(identifier: "NotificationID\(i)", content: content, trigger: trigger) let center = UNUserNotificationCenter.current() center.add(request) { (error) in print(error?.localizedDescription ?? "") } } } |
Conclusion
I know that I haven’t described anything in detail. If I get time I will update this blog with details.
Happy Coding ?
If you have any questions, comments, suggestions or feedback then contact me on Twitter @ashishkakkad8.
Tips for update CocoaPods and your project libraries
CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects.
CocoaPods is built with Ruby and is installable with the default Ruby available on OS X. We recommend you use the default ruby.
Update your system
Update your system by following command in terminal.
1 |
$ sudo gem update --system |
Above command will install/update rubygems.
Install CocoaPods
Install CocoaPods in your system by following command in terminal.
1 |
$ sudo gem install cocoapods |
If you are getting errors above command then use following command.
1 |
$ sudo gem install -n /usr/local/bin cocoapods |
Check CocoaPods Version
1 |
$ pod --version |
Update CocoaPods Repository
We have to update CocoaPods repository with latest pod updates by developers. Use following command to update CocoaPods repository:
1 |
$ pod repo update |
It will take some time to update all sub repositories.
Update pod for your project
If you directly apply the command pod install then some time new pods will not be updated in your project. For that you have to remove that specific pod information from the pod file and you have to apply pod install command. It will remove pod from the project. After that again you have to add the pod information in the pod file. Again you have to apply pod install command to install new version of pod.
Follow the next steps:
1. Remove SomePod
from the Podfile
2. Run pod install
pods will now remove SomePod
from our project and from the Podfile.lock
file.
3. Put back SomePod
into the Podfile
4. Run pod install
again
This time the latest version of our pod will be installed and saved in the Podfile.lock
.
You can update single pod file as follows:
1 |
$ pod update 'POD_NAME' |
Remove all CocoaPods from a project
Install CocoaPods deintegrate and clean commands from terminal.
1 |
$ sudo gem install cocoapods-deintegrate cocoapods-clean |
Now you have to apply both command to remove all CocoaPods from your project:
1 2 |
$ pod deintegrate $ pod clean |
Happy Coding ?
List of known Xcode issues
Xcode is IDE for development of the iOS, macOS, tvOS and watchOS applications. Every year apple comes up with so many changes in this IDE. Xcode 9.3 released on March 29, 2018.
Here, I am listing out all the issues with the workaround.
How to use Alamofire with Codable in Swift?
Hello after long time I am writing this blog regarding use of Alamofire with Codable model object for the ease of MVC architecture.
Let’s rewind with some of the post which is used to cover this point:
- How to use Alamofire and SwiftyJSON with Swift?
- How to create a wrapper for Alamofire and SwiftyJSON?
- Use of Codable and Coding Key with JSONEncoder and JSONDecoder in Swift 4
Let see about use of Alamofire with Codable model object
Step 1 – Create Codable object based on JSON response.
Here I am taking an example of a web service which contains JSON related to the contact.
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "id": "c200", "name": "Ravi Tamada", "email": "ravi@gmail.com", "address": "xx-xx-xxxx,x - street, x - country", "gender" : "male", "phone": { "mobile": "+91 0000000000", "home": "00 000000", "office": "00 000000" } } |
So, we can create two Codable files from this JSON as per hierarchy. These would be like as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
struct Contact: Codable { var id : String var name : String var email : String var address : String var gender : String var phone : Phone } struct Phone: Codable { var mobile : String var home : String var office : String } |
As you can see we have created 2 objects Contact and Phone. Here Phone is in sub hierarchy.
Step 2 – Let’s update AFWrapper
As we have previously revised blogs, there is a blog mentioned about to create a wrapper of the Alamofire and SwiftyJSON. We have to replace the SwiftyJSON code to return normal dictionary objects, and after that we will convert that dictionary to the Codable object.
So here I have updated the AFWrapper class file to do that thing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import UIKit import Alamofire class AFWrapper: NSObject { class func requestGETURL(_ strURL: String, success:@escaping ([String : Any]) -> Void, failure:@escaping (Error) -> Void) { Alamofire.request(strURL).responseJSON { (responseObject) -> Void in print(responseObject) if responseObject.result.isSuccess { success(responseObject.result.value! as! [String : Any]) } if responseObject.result.isFailure { let error : Error = responseObject.result.error! failure(error) } } } } |
Step 3 – Implement and convert the response in object
We will call a web service which contain that kind of JSON response. And after calling the web-service we will decode the object to create the Codable object.
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 29 30 31 |
import UIKit class ViewController: UIViewController { var arrContacts = [Contact]() @IBOutlet var txtContacts: UITextView! override func viewDidLoad() { super.viewDidLoad() AFWrapper.requestGETURL("https://api.androidhive.info/contacts/", success: { (responseObject) in print(responseObject) for aContact in responseObject["contacts"] as! [Any] { do { let jsonData = try JSONSerialization.data(withJSONObject: aContact, options: .prettyPrinted) let reqJSONStr = String(data: jsonData, encoding: .utf8) let data = reqJSONStr?.data(using: .utf8) let jsonDecoder = JSONDecoder() let aContact = try jsonDecoder.decode(Contact.self, from: data!) self.arrContacts.append(aContact) self.txtContacts.text = self.txtContacts.text + aContact.name + " " + aContact.phone.mobile + "\n" print(self.arrContacts) } catch { } } }) { (error) in print(error.localizedDescription) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } |
In above sample I have added one text view in the view controller and I am fetching the data from the contacts API. After that using JSONSerialization and JSONDecoder we will get our decoded Contact object with Phone object.
Conclusion
Swift 4 comes with so many updates. We are going to have a great time exploring them all and finding out so much more by using it on further projects. We have learned about Codable and use of it. You too should go check it out and share your experiences with us in the comments section.
Hope you liked the article.
Happy Coding 🙂
What's new in Xcode 8.3?
Swift 2.3 Deprecation
- Xcode 8.3 beta 2 no longer supports Swift 2.3. Please migrate your projects containing Swift 2.3 code to Swift 3 syntax by opening the project and choosing Edit > Convert > To Current Swift Syntax.
Other Deprecations and Removal Notices
- The Automation instrument has been removed from Instruments. Use Xcode’s UI Testing in its place.
Organizer
- The Xcode Organizer now supports exporting tvOS apps for Enterprise distribution.
Testing
- Added the XCUISiriService class to XCTest for writing tests which activate Siri with a voice recognition string, and queries for elements in the Siri UI. Use the class to write UI tests for Intents and Intents UI extensions.
Swift Compiler
- The Swift compiler can now automatically precompile Objective-C bridging headers, which can speed up Debug configuration builds (or other non-WMO builds) of mixed-source projects with large bridging headers. This feature is still experimental, and is disabled by default but can be enabled with the “Precompile Bridging Header” (SWIFT_PRECOMPILE_BRIDGING_HEADER) build configuration setting within Xcode.
Provisioning
- Changed the user interface for managing signing certificates and provisioning profiles. Certificates are managed from the Accounts preferences pane by selecting a team and clicking Manage Certificates. Automatically managing signing is recommended, however if your app requires manually signing provisioning profiles are managed in the General tab of the project editor. Use the Provisioning Profile dropdown to import or download profiles. In addition it displays profiles that match the current signing configuration of the target.
Simulator
- You can invoke Siri using Hardware > Siri after enabling Siri in the Settings app on Simulator.
Others
- Xcode 8.3 includes Swift 3.1 which is intended to be source compatible with Swift 3.0.
- Constrained extensions allow same-type constraints between generic parameters and concrete types. For example, the following code defines an extension on Array with Int elements:
1extension Array where Element == Int { } - The Swift compiler now raises an error for modifications of a let property or variable of protocol type after initialization. For example, the following code that compiled in previous versions will now raise an error:
1234567891011protocol P {mutating func f()}extension Int: P {mutating func f() { self += 1 }}func foo(x: Int) {let y: Py = xy.f()}Code that successfully compiled in previous releases may fail after upgrading.
Interface Builder
- NSTextField objects created in Interface Builder now have allowsCharacterPickerTouchBarItem turned off by default.
Currently latest beta version is Xcode 8.3 Beta 3. I will update this blog as per versions of Beta.
Happy Coding 🙂