How to show an error in apple watch - ios

How to handle exception cases like offline error in apple watch, i can not find anything about this in Apple Watch Programming Guide.
Is apple watch support overlay text? or need make error ui by myself.

WatchKit does not provide alert or error UI yet (as of March 2015). You will have to make one yourself.
One easy way is to make a custom class that implements WKInterfaceController and create the interface in Storyboard. Then use presentControllerWithName:context: to display it modally.
ErrorInterfaceController:
import WatchKit
import Foundation
class ErrorInterfaceController: WKInterfaceController {
#IBOutlet weak var errorMessageLabel: WKInterfaceLabel?
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context);
if let dictionary = context as? [String: String] {
if let message = dictionary["message"] {
errorMessageLabel!.setText(message)
}
}
}
#IBAction func closeModalView() {
dismissController()
}
}
Method to show the custom error UI modally:
private func showError(#message: String!) {
presentControllerWithName("ErrorInterfaceController", context: ["message": message]);
}

WatchKit does not provide any type of alert similar to UIAlertController you'd find in UIKit.
You can present a new interface controller and show details on that screen, then add buttons to it if the user needs to take action (for example to dismiss it).

To display error text in your WatchKit app, you can use label objects.
Labels support formatted text that can be changed programmatically at runtime.

Related

how to detect UIview lost focus or get focus in swift 4?

I'm developing in a scroll view a page, where there is some youtube videos with YoutubeKit framework.
YoutubeKit is using UIView to show video. I would like to pause video when the UIView isn't in focus (not shown but user).
isfocused() is working but I would like to get "an event", to automatically react when the focus is lost.
i understood I need to create a custom UIview class to override canBecomeFocused
here is the code of the custom class I've created
import Foundation
import UIKit
class focusableUIview: UIView {
override var canBecomeFocused: Bool {
return true
}
override func didUpdateFocus(in context: UIFocusUpdateContext, withcoordinator: UIFocusAnimationCoordinator) {
print("focus")
}
}
I've also updated story board on changing the class of the UIView i want to detect focus change.
what I'm questioning, what I need to do in the UIviewcontroller class, I've noticed canBecomeFocused is never called...
I'm a bit lost. many thanks for your help
Make your view focusable
override var canBecomeFocused: Bool {
return true
}
Then override this function to get update on focus
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
}
I think focus-based UI system is for tvOS. UIKit can be used to develop apps for Apple TV. But focus has no effect on iOS.
A UI element is in focus when the user highlights an item, but has not selected an item.
https://developer.apple.com/library/archive/documentation/General/Conceptual/AppleTV_PG/index.html#//apple_ref/doc/uid/TP40015241-CH12-SW1

How to share selected text with my application?

I would like to make my app appear in the UIActivityViewController for text sharing, like in Mail, iMessage, Notes, Gmail etc etc.
For example, when user tapback on selected text and hit the 'Share' button from any app like in the attachment:
I would like my app to appear in the UIActivityViewController and when the user selects my app, to launch it with the ability to handle that selected text.
So what I have tried:
Search in Apple documentation.
Searched for relevant UTI but I understood that the UTIs are used only for files and not for a simple NSString (Correct me if I'm wrong).
I have tried to implement Share Extension, but this is not the solution that i want, I don't need the post popup and moreover than that I need to launch my app after sharing like in Mail, Notes, iMessage does (Regarding to Apple documentation we can't launch the contain app through Share extension only through Today extension).
Of course, I have searched a lot in StackOverFlow.
So any solutions?
Thanks!
Assume that you already have some app.
Add Target File -> New -> Target. In
the left pane, select Application Extension from the iOS section,
choose Action extension, and click Next.
Set the Product Name. Make sure the Action Type is Presents user interface. Click Finish.
In the Project Navigator, expand the extension group and click on MainInterface.storyboard. Select the image view and replace it with UITextView. Create and bind #IBOutlet weak var to it.
Select Info.plist of the extension, navigate to NSExtension -> NSExtensionAttributes -> NSExtensionActivationRule. Change the NSExtensionActivationRule's type from String to Dictionary. With the dictionary expanded, click the + button next to it. This will add a child key. Set its name to NSExtensionActivationSupportsText, its type to Boolean, and the value to YES. This ensures that the action extension is only visible when at least one input item contains text.
Put this code to ActionViewController.swift:
_
import UIKit
import MobileCoreServices
class ActionViewController: UIViewController {
#IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
// Get the item[s] we're handling from the extension context.
var textFound = false
for item in self.extensionContext!.inputItems as! [NSExtensionItem] {
for provider in item.attachments! {
if provider.hasItemConformingToTypeIdentifier(kUTTypePlainText as String) {
// This is an plain Text.
weak var weakTextView = self.textView
provider.loadItem(forTypeIdentifier: kUTTypePlainText as String, options: nil, completionHandler: { (textItem, error) in
OperationQueue.main.addOperation {
if let strongTextView = weakTextView {
if let gotText = textItem as? String {
strongTextView.text = gotText
// do what you need with the text
}
}
}
})
textFound = true
break
}
}
if (textFound) {
// We only handle one text, so stop looking for more. You can do as you need.
break
}
}
}
#IBAction func done() {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
self.extensionContext!.completeRequest(returningItems: self.extensionContext!.inputItems, completionHandler: nil)
}
}

Add data in segue won't recognize SecondViewController class when running

So here is my first view controller class:
import UIKit
class AboutUsTableViewController: UITableViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let volunteerPageVC = segue.destination as! DedicatedVolunteerViewController
// Idk why I have to use 'as!' instead of 'as'. Xcode made me do it
volunteerPageVC.person = "John Smith"
}
}
Here is my second view controller class:
import IUKit
class DedicatedVolunteerViewController: UIViewController {
var person: String?
#IBOutlet weak var HeaderTitle: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
HeaderTitle.text = "About " + person!;
}
}
On my Main Storyboard, each of the cells on the AboutUsTableView segue to the DedicatedVolunteerViewController. I want to ability to have one view controller that can be used multiple times (i.e. people's profiles).
When I click on any of the cells in the table view, I get these errors:
2016-12-26 11:44:27.075 MyApp iOS[8350:493673] Unknown class _TtC20MyApp_iOS31DedicateVolunteerViewController in Interface Builder file.
2016-12-26 11:44:29.698 MyApp iOS[8350:493673] Unknown class _TtC20MyApp_iOS31DedicateVolunteerViewController in Interface Builder file.
I'm confused since when I compile the app, it gives no error saying about "Unknown class" or an error saying I need to add/import DedicatedVolunteerViewController into AboutUsTableViewController to be able to use it. I even tried to import it, but Xcode wouldn't let me and kept giving me errors.
P.S. I've a lot of trouble considering most places online give documentation on older versions of swift or obj-c which make it hard to find out how to use new versions of code.
It sounds like the class name is wrong in your storyboard scenes. Go follow the segue(s) from your table view controller to your second view controller. Then select the scene for the destination view controller, select the view controller itself, and select the "identify inspector." Check the class of the destination view controller. From the error you're getting, it sounds like it's class is _TtC20MyApp_iOS31DedicateVolunteerViewController instead of DedicateVolunteerViewController.
Swift uses 'optionals' which essentially means a nullable object. Optionals can have a valid value or nil. It is recommended that you use the 'guard' statement to handle optionals.
So, your prepareForSegue should look like:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let volunteerPageVC = segue.destination as? DedicatedVolunteerViewController else {
//Handle the nil value, log, etc
return
}
volunteerPageVC.person = "John Smith"
}
The ! is explicitly unwrapping the optional - meaning it MUST have a value or the app will crash. You should avoid using them where possible and use the ? as I show above instead with a guard statement. In the code above, it attempts to cast the segue.destination to a DedicatedVolunteerViewController but if it can't, it will fall into the guard statement (meaning the result was nil).
There's a lot of good information about optionals on Apple's site. Check out: Swift Basics
As for your specific error, it looks like a simple mis-spelling. The error is referring to 'DedicateVolunteerViewController' (missing a 'd') and your class name is 'DedicatedVolunteerViewController'

Where to put logic shared by multiple view controllers

I'm working on an iPhone app (Objective-C) which has barcode scanning functionality on many of its screens. The user can tap a control to recognize different barcodes and navigate to different screens depending on what type of barcode is recognized. The majority of the logic does not depend on which screen they initiated the scan from... As such, I don't want to duplicate the code in each view controller, but am uncertain where the best place for it is. It requires the user tapping on a detection rectangle, so it does need to be able to handle these events. Many thanks!
You could use a singleton
class DataStore {
static let sharedDataStore = DataStore()
func scanBarcode() {
//logic
}
}
calling the function in another View Controller
class viewController: UIViewController {
let shared = DataStore.sharedDataStore
override func viewDidLoad() {
//calling the function
shared.scanBarcode()
}

Pass data when dismiss modal viewController in swift

I'm trying to pass data from the modal ViewController to his source ViewController. I think I have to use delegation but it doesn't work.
protocol communicationControllerCamera{
func backFromCamera()
}
class Camera: UIViewController{
var delegate: communicationControllerCamera
init(){
self.delegate.backFromCamera()
}
}
class SceneBuilder: UIViewController, communicationControllerCamera{
func backFromCamera(){ // Never called
println("YEAHH")
}
}
The backFromCamera method it's not called. What did I do wrong?
You didn't set a delegate so it was empty when you tried to call backFromCamera().
Here's a simple working example you can test out. Notice the use of the optional type (?) for the delegate.
// Camera class
protocol communicationControllerCamera {
func backFromCamera()
}
class Camera: UIViewController {
var delegate: communicationControllerCamera? = nil
override func viewDidLoad() {
super.viewDidLoad()
self.delegate?.backFromCamera()
}
}
// SceneBuilder class
class SceneBuilder: UIViewController, communicationControllerCamera {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
var myCamera = Camera()
myCamera.delegate = self
self.presentModalViewController(myCamera, animated: true)
}
func backFromCamera() {
println("Back from camera")
}
}
You can find all the information you need in Apple's Swift documentation.
Obviously the chosen answer is correct, but it didn't help me. I did successfully implement protocols though, so I wanted to provide my own explanation in case anyone is struggling with grasping the concept, like I was.
Protocol Code Is Written in Three Places:
Two ViewController Classes
The Protocol itself (code written outside of VC classes)
When I write my protocols, I put them in my "ToolBox" document and I still write comments to remind myself which VCs are doing what. Two examples:
So there is always:
The protocol code (shown above)
Code in a VC which initiates the action
Code in a VC which is delegated to carry out the action
1. The protocol code
See the image above for a reference. Essentially, the protocol code is just where you give the protocol a name and declare what functions you want to remotely call/delegate to. Name the protocol. Declare the names of the functions that can be called upon and declare their parameter types such as string, etc.
2. Code in a VC which initiates the action
This is the code that initiates the protocol. In this example, this is code from a table cell, which needs to delegate some work back to the main table VC. The first screenshot shows the creation of the delegate variable and the second screenshot is the actual use of that variable.
So the below code are table-cell buttons. They all need to trigger code outside of the cell VC, so they all trigger functions using the protocol I declared above.
3. Code in a VC which is delegated to carry out the action
Now the protocol is being called, but which VC answers the call? To answer that question, choose the VC and add the protocol name to the class declaration:
Lastly, you need the actual meat of the whole thing. Not the trigger, not the protocol itself, not the class declaration... but the actual function you want to call:
Hope This Helps
I don't know why protocols just wouldn't sink through my thick skull but they wouldn't. I hope this helps others like me!

Resources