Reference non-initiated variable at top of file - swift

this is a bit odd to say but essentially here is my code below:
import UIKit
class BarcodeScanPopover: UIViewController, UIPopoverPresentationControllerDelegate {
#IBOutlet weak var navbar: UINavigationItem!
#IBOutlet weak var product: UILabel!
#IBOutlet weak var productimage: UIImageView!
#IBOutlet weak var scanner: UIView!
var scan: MTBBarcodeScanner = MTBBarcodeScanner(previewView: scanner);
override func viewDidLoad() {
So the issue I'm having is I can't declare "scan" without initiating the MTBBarcodeScanner object, but at the same time, I can't initiate the MTBBarcodeScanner object without calling "scanner" which is not possible at the top of the file. Unfortunately MTBBarcodeScanner() is not a valid init and causes crashes so that is not possible either.
I need to do this because I need to access "scan" at different points in the code - not just in one code method.
Any suggestions?

If you are sure you will always have an instance of the MTBBarcodeScanner after the view loaded, declare it as MTBBarcodeScanner!: var scan: MTBBarcodeScanner!. That makes it an implicitly unwrapped optional, which is allowed to be nil unless you try to access some property/function on it.
You should therefore then make sure that you always assign something to it before ever accessing it in any other way. That can and should be done in viewDidLoad:
scan = MTBBarcodeScanner(previewView: scanner)

You can let your MTBBarCodeScanner instance be an optional, and initially set it to nil.
var scan: MTBBarcodeScanner? = nil
Thereafter call your initializer to update its value as soon as scanner instance is available to you (e.g. in viewDidLoad).

Related

Swift - Can't access struct properties

Learning swift but a little confused as to the below. I have struct created and instantiated, but I cannot access the property of the struct inside of my view controller class unless the struct is inside one my my class methods. See below, why would this be the case?
class WeatherViewController: UIViewController, UITextFieldDelegate, WeatherManagerDelegate {
//create new weather manager struct
var weatherManager = WeatherManager()
//can't access property here, but I can access it inside of functions within this
//class, see below under viewDidLoad()
weatherManager.delegate = self
#IBOutlet weak var conditionImageView: UIImageView!
#IBOutlet weak var temperatureLabel: UILabel!
#IBOutlet weak var cityLabel: UILabel!
#IBOutlet weak var searchTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//can access property here
weatherManager.delegate = self
}
The problem isn't where the WeatherManager object is declared and created. The problem is that this line:
weatherManager.delegate = self
is a command (technically a statement), not a declaration. (The line above it is a declaration, one that happens to also set the weatherManager property's default value). This is a pretty universal rule in most languages in the C++/Java family -- see short C++ example below. A command (statement) must be inside some method (or function, in non-OOP programming), not at the top level of a file or class. In Swift, actions like setting an object's delegate would typically go in the view controller's viewDidLoad.
int x = 0; // legal: declaring a global variable
x = x + 42; // NOT legal: this is a statement, not a declaraiton
int main()
{
x = x + 42; // legal: now we're inside a function
return 0;
}

why do i keep getting “AnyObject cannot be constructed because it has no accessible initializers”

I have been following a tutorial on youtube and been coding a twitter like app in xcode and keep returning this error, the tutorial was using an earlier version of swift. How do i move past this?
class HandleViewController: UIViewController {
#IBOutlet weak var fullName: UITextField!
#IBOutlet weak var handle: UITextField!
#IBOutlet weak var startTweeting: UIBarButtonItem!
#IBOutlet weak var errorMessage: UILabel!
var user = AnyObject()
var rootRef = FIRDatabase.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
self.user = FIRAuth.auth()?.currentUser
}
You're getting that error because AnyObject in Swift is a Protocol, not a class, structure, or enum. A protocol is sort of a blueprint for a class, and you create classes that conform to it, but the protocol itself can never be instantiated.
As for how to fix it: It looks like the tutorial you're following uses the same code as the tutorial here. It assigns a value to user in viewDidLoad, and treats it as an optional after that. So the initial value is just a placeholder that's never getting used.
You can change the declaration to an optional instead, giving it a type but no value:
var user: AnyObject?
AnyObject has always been a Protocol in Swift, so there could never be an instance of it. So why did it work in the previous version of Swift used in the tutorial? Well for one, it looks like there's a typo in your version. In the tutorial it looks like this:
var user = AnyObject?()
The question mark after AnyObject? makes it an Optional of type AnyObject. In Swift prior to 3.0, Optional had an init() method that would create an empty instance. So AnyObject?() was shorthand for a new Optional of type AnyObject, value set to nil. In Swift 3 the superfluous initializer was dropped, so that shorthand no longer works. But just declaring the variable as an optional has the same effect.

Could not find initializer for type 'TableCell' that accepts an argument list of type

XCODE: Swift
Full Error:
Could not find initializer for type TableCell that accepts an argument list of type caseImage: (UIImge, caseName: String, caseDate: String)
var patientCaseArray = [TableCell]()
func loadSampleData() {
let Photo1 = UIImage(named: "retino1")!
let case1 = TableCell(caseImage: Photo1, caseName: "John Smith", caseDate: "2015-10-18" )
//error
patientCaseArray = [case1]
}
Working on a table cell class defined elsewhere, with this set of IBOutlets:
#IBOutlet weak var caseImage: UIImageView!
#IBOutlet weak var caseName: UILabel!
#IBOutlet weak var caseDate: UILabel!
I haven't done anything to the class except add the outlets.
I'm very new to swift and I'm going through a tutorial which says this is supposed to compile fine. It isn't supposed to input to the table yet. What am I missing?
Thanks in advance.
You have a discrepancy in types:
Could not find initializer for type 'TableCell' that accepts an
argument list of type caseImage: '(UIImge, caseName: String,
caseDate: String)'
and
#IBOutlet weak var caseImage: UIImageView!
UIImageView is not the same as UIImage, you will need to decide which one you want to use.

weak cannot be applied to non-class type uiimageview

I have a class in swift that needs to have a weak pointer to an array of objects that is allocated in another class. I have
class myView: UIView
{
var lines:[CAShapeLayer] = []
weak var avatars : [UIImageView]?
The error I get is
'weak' cannot be applied to non-class type '[UIImageView]'
I also tried to no avail:
weak var avatars : [UIImageView?]?
Weak Cannot be applied to non-class type:
It means you can’t have a weak reference to any value type instance(e.g. Array, Dictionary, String, etc…) because these all are struct not class. You only give weak reference which are of class-type(e.g UIImage, UIImageView, etc…).In this case, you are trying to give weak reference to UIImageView Array and we know array is a value type, so it is not possible.
For example:
weak var str: String? //CompileTime Error(Wrong)
weak var arr: Array? //CompileTime Error(Wrong)
weak var imageView: UIImageView? //Correct
In case of Protocol:
If we have just a protocol of struct type:
protocol SomeProtocol{
func doSomething()
}
We cannot declare variables of this type as weak:
weak var delegate: SomeProtocol? //CompileTime Error(Wrong)
But if we make protocol of class type like this:
protocol SomeProtocol: class{
func doSomething()
}
We can declare variables of this type as weak:
weak var delegate: SomeProtocol? //Correct
I think you easily understand it, why this happens in protocol?
Same reason: You only give weak reference which are of class-type
needs to have a weak pointer to an array of objects
Well, as the error message tells you, you can't. Array is a struct, not a class. You can't have a weak reference to a struct instance; it's a value type, so it doesn't do weak memory management.
Nor does it need it - there is no danger of a retain cycle, because this is a value type. You should ask yourself why you think it does need it. Perhaps you think weak and Optional always go together, but they do not. You've already declared this an Optional array; that is enough, surely.
You're trying to apply weak to an Array of type UIImageView. Array is a struct.

Swift: ! instead of = nil

I've recently taken up Swift in order to learn how to program iOS apps. I've been following Skip Wilson's tutorials and there's a moment when he connects an outlet and gets:
#IBOutlet var ticTacImg1: UIImageView = nil
instead of getting that I obtain:
#IBOutlet var ticTacImg1: UIImageView!
if I try to change it Xcode tells me it's an error. What am I doing wrong?
In early versions of Xcode 6, anything marked as #IBOutlet was turned into a weak implicitly unwrapped optional.
That is
#IBOutlet var ticTacImg1: UIImageView = nil
would be compiled as
#IBOutlet weak var ticTacImg1: UIImageView! = nil
This is no longer true. Now you must declare its optional status, but it will still be weak.
That is
#IBOutlet var ticTacImg1: UIImageView! = nil
would be compiled as
#IBOutlet weak var ticTacImg1: UIImageView! = nil
The reason why ticTacImg1 is not initialized to nil is that it doesn't matter. In Swift, implicitly unwrapped optionals which are not initialized have the value nil, so = nil is redundant.
#IBOutlet var ticTacImg1: UIImageView! is the correct code.
An #IBOutlet property needs to be optional because it initially has a nil value before the system connects the view to it. Marking it as an implicitly unwrapped optional with ! means that it will be unwrapped automatically whenever it is used.
I'm not sure which specific tutorial you're referencing, but my initial thought is that he could be using an early beta of Xcode 6 that didn't enforce this.