Cannot assign value of type ViewController to type UITabBarControllerDelegate? - uitabbarcontroller

I have spent a few hours on this one, as I thought first that it was again an issue while migrating to swift2 with AnyObject versus PFObject. But apparently not! Here is the code:
class TimelineViewController: UIViewController, TimelineComponentTarget {
var timelineComponent: TimelineComponent<Post, TimelineViewController>!
override func viewDidLoad() {
super.viewDidLoad()
timelineComponent = TimelineComponent(target: self)
self.tabBarController?.delegate = self
}
Xcode returns on the 'self' of the last line:
Cannot assign value of type 'TimelineViewController' to type 'UITabBarControllerDelegate?'
Any help would be really appreciated, I would love to finally compile my code :)
Thanks!

I understood from the error message that I was trying to assign self as the delegate of a UITabBarControllerDelegate.
Or the TimeLineViewController is not a UITabBarControllerDelegate. I have therefore adopt this protocol.
class TimelineViewController: UIViewController, TimelineComponentTarget, UITabBarControllerDelegate {
It now works properly. Thanks!

Related

Mismatch between widget size and #Environment value in TimelineProvider

Morning, everyone,
I'm developing a widget using an API that sends an array of different sizes depending on the size of the widget (small : 3 news, medium: 6 news, large: 9 news).
I have the impression that there is a problem between the #Environment(\.widgetFamily) var family and the timeline function (where I call the API) of TimelineProvider.
Indeed in this function the environment variable is always equal to the systemMedium size despite the "real" size of the widget.
Do you also have the same problem on your side ?
Is it a known bug from Apple ?
How can I solve this bug ?
Thanks for your help :]
Without seeing your code, my best guess is that you're not accessing the family property of the TimelineProviderContext passed into the TimelineProvider.
Your TimelineProvider should look something like:
struct MyProvider: TimelineProvider {
func snapshot(with context: Context, completion: #escaping (Entry) -> ()) {
fetchNewsArticles(for: context.family) { articles in
// ...
completion(...)
}
}
}
func fetchNewsArticles(for widgetFamily: WidgetFamily, completion: #escaping ... )
{
switch family {
case .systemSmall:
// ...
}
Apple Docs - TimelineProvider
Apple Docs - TimelineProviderContext

Swift. Error in working with UIApplication.shared

This question, in the old program that is implemented under UIKit, was done like this.
Condition in which the following actions are performed:
if(theApp().m_Disp.Connecttosrv(self.SelCon)) {
In the condition, the function is accessed
func theApp() -> iSPultApp!
{
return UIApplication.shared as? iSPultApp
}
Where next the class is called from the function
class iSPultApp: UIApplication {
var m_Disp: Chroot = Chroot()
Everything works there, is it possible to redo it somehow for SwiftUI?
The program goes to func theApp (), and then instead of going to the class, returns to the condition and there is an error:
if(theApp().m_Disp.Connecttosrv(self.SelCon)) {
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value.
self.SelCon is not empty, but filled with data. apparently, nil is passed in func theApp()
Thank you in advance for your help 🙏

Global variable in swift 3

I have the variable provincias_ws which has the answer of a service, so far everything is fine but I want to know how I make the variable provincias_ws is global since I want to print it in the textFieldDidBeginEditing method
class ViewCtrl: UIViewController, ValidationDelegate, UITextFieldDelegate {
#IBOutlet weak var txt_ciudadU: SearchTextField!
override func viewDidLoad() {
super.viewDidLoad()
opciones_autocompletado()
txt_ciudadU.delegate = self
}
func opciones_autocompletado(){
txt_provinciaU.inlineMode = true
txt_ciudadU.inlineMode = true
Services.objServices.ServProv().then{
data -> Void in
let res = JSON(data)
let status = res["status"].boolValue
if(status){
let provincias_ws = res["data"]["provincias"] //How to make this variable global
}else{
let error = res["error"]["error_data"].stringValue
print(error)
}
SVProgressHUD.dismiss()
UIApplication.shared.endIgnoringInteractionEvents()
}.catch{
error -> Void in
SVProgressHUD.dismiss()
UIApplication.shared.endIgnoringInteractionEvents()
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print(provincias_ws)
}
}
Thank you in advance
One can create a "global" variable (meaning it can be access from anywhere in the project) by defining it outside of the class block.
However, it looks like what you want is a class instance variable.
Your text field txt_ciudadU is already an example of an instance variable or property of the class ViewCtrl.
This would be the same, just without #IBOutlet weak.
So would probably be (assuming it's a String):
var provincias_ws: String?
Note the ? declares it as an optional value because it will not be set until it gets set inside your block. You could also initialize it to some default or empty value (e.g. var provincias_ws = "") or you could use ! to indicate you won't be trying to unwrap it when it's nil, although it's better not to rely on that because it is error-prone. What you choose to do depends on your needs.
And you would put that at the same hierarchical level as your text field variable (i.e. right above or below it, although it could go anywhere really, as long as it's not inside a function or another block).
And you would get rid of the current let next to provincias_ws and prepend it with self. i.e.:
self.provincias_ws = res["data"]["provincias"]
The self. is necessary because it's inside a block and the compiler needs that for context.

access methods from protocols to viewcontroller

I was just implementing object class to access methods and protocols. Following
import UIKit
import Foundation
import Alamofire
import SVProgressHUD
protocol ParseAPIProtocol:class {
func APIresponse(responseDict: NSDictionary)
}
class ParseAPI :NSObject{
// weak var mydelegate : MyProtocols?
weak var delegateAPI:ParseAPIProtocol?
class func ParseUrl(postparameters: [String: AnyObject]!, url:String, current:UIViewController) {
print(postparameters)
print(url)
SVProgressHUD.show()
Alamofire.request(url, method: .post, parameters: postparameters, encoding: URLEncoding.default, headers: nil).responseJSON
{
(response:DataResponse<Any>) in
switch(response.result)
{
case .success(_):
if response.result.value != nil
{
let jsonResult = (try! JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSDictionary
print(jsonResult)
}
break
case .failure(_):
SVProgressHUD.dismiss()
print(response.result.error as Any)
break
}
}
}
Whenever I got the jsonResult, I just want to call fun APIresponse to parse result dictionary to viewcontroller class.
I declared the method on viewcontroller and its delegate.
But when I tried to call protocol method, it doesn't give me access to the method. May be I am doing something wrong. Please look into my method.
Thanks!
The way I see it there are several issues, although it's hard to tell because you don't show the relevant code in your view controller
(how you set up the delegate, how you call your parse API).
First, you never call your delegate with the result. With your current setup this isn't even possible: you define ParseAPI to have a
delegate (instance) member but define ParseUrl as a class func. I guess this is what you meant when saying "it doesn't give me access to the method".
Try defining it as a member function and then, in the success case call the delegate:
self.delegateAPI?.APIresponse(responseDict: jsonResult)
In your view controller, instantiate a ParseAPI instance and keep it alive (for example by storing it in a strong instance member), set its delegate,
and call ParseUrl(...). This call will return pretty much immediately and later, when the request and response is handled, your delegate method will
be called.
class ViewController: UIViewController, ParseAPIProtocol
{
var parser: ParseAPI?
func somewhere()
{
self.parser = ParseAPI()
self.parser!.delegateAPI = self
self.parser!.ParseUrl(postparameters: [:], url: "...", current: self)
}
func APIresponse(responseDict: NSDictionary)
{
print("VC got response:", responseDict)
}
}
Second, the current parameter is never used, you can remove it. Either that or you can remove the whole delegate thing and replace the current parameter
with a callback, something like this:
func ParseUrl(postparameters: [String: AnyObject]!, url:String, finished: #escaping (_ response: NSDictionary?) -> Void)
{
...
// success case:
finished(jsonResult)
// failure case:
finished(nil)
}
and call it like this:
self.parser!.ParseUrl(postparameters: [:], url: "...", finished: { (response: NSDictionary?) in
// handle response
})
You can also define your callback to have an error parameter so you can act accordingly when one occurs.
And finally, while I don't know SVProgressHUD, you probably wanna call SVProgressHUD.dismiss() in the success case, too.

Error "Value of type ... has no member" while calling self in lazy property closure

Why the following Swift3 code results in error value of type (NSObject) -> () -> MyView has no member getSomeButton in Xcode 8?
lazy var someButton = {
return self.getSomeButton // ERROR
}()
private func getSomeButton() -> UIButton {
return UIButton()
}
Actually, the error message is totally misleading and should be something like can't infer closure return type. Specifying variable type solves the problem. Hope this help someone.
lazy var someButton: UIButton = {
return self.getSomeButton // OK
}()