I'm new to iOS. I want to know how to create a non UIViewController based class. I mean to say the class not extending from UIViewcontroller.
I want so because I want to call some Async HTTP url and parse the Json/XML in non UI class. I just want to do them in a separate class from UIViewcontroller classes.
Create a new class without inheritance like this:
class JSONObject{
var url: NSURL?
internal func parseJSON() -> NSArray {
// Code to parse your json
return []
}
}
and then you can create an instance of the class elsewhere using something like this:
var newJSONObject: JSONObject = JSONObject()
newJSONObject.url = NSURL(string: "www.somejson.php")
newJSONObject.parseJSON()
Related
Perhaps I'm still thinking in an Objective-C kind of way. I'd like to register classes to be used in a factory pattern. The classes conform to a protocol such as:
protocol URLNavigation: class {
static func canHandle(url: URL) -> Bool
static func instantiate(with url: URL) -> UIViewController?
var url: URL? { get set }
}
and then in my Factory class have something like:
var registeredTypes: [UIViewController.self & URLNavigation]
But I know the line above is incorrect. I'm trying to keep a references to class objects that will be used to instantiate instances of those classes.
And am also wondering how I would instantiate these using an element in this 'registeredTypes' array.
I hope it's clear what I'm trying to accomplish. Perhaps there's another approach?
You can do like this.
var registeredTypes: [(UIViewController & URLNavigation).Type].
I wish to avoid writing let APIHelper = API() in every UIViewController, instead I did this:
extension UIViewController {
func APIHelper() -> API {
let api = API()
return api
}
}
and now it is working like self.APIHelper().callMethod(), but I'm not really sure if it is the way to do it. Any tips on best practice?
Your extension useless, since it just same as calling API() everytime:
self.APIHelper().callMethod()
self.APIHelper().callSecondMethod() //here you created another API instance
same as
API().callMethod()
API().callSecondMethod()
If API is singletone, idea looks ok, but in swift you usually create singletone with static constant:
class API {
static let sharedAPI = API()
//...
}
and access to it like this:
API.sharedAPI.callMethod()
API.sharedAPI.callSecondMethod() //now called in same API instance
If you don't want to write API.sharedAPI everytime, then you can use:
Your extension
extension UIViewController {
var apiHelper: API {return API.sharedAPI}
}
Not recommended as #NickCatib explained.
Base view controller
as #NickCatib suggested (easier with variable):
class BaseViewController: UIViewController {
// some of the code you might need
let apiHelper = API.sharedAPI
}
Protocol
If you use API in view controllers time to time, can be better declare protocol
protocol APIHelper {
var apiHelper: API {get}
}
with default implementation
extension APIHelper {
var apiHelper: API {return API.sharedAPI}
}
and connect it to your viewController only when needed
class ViewControllerThatNeedsAPI: UIViewController, APIHelper {
// apiHelper avalible here
}
With all three ways you access your API like this:
apiHelper.callMethod()
How about some kind of base view controller where you can extend with that declaration? This way ALL of your view controllers have that function, even when you don't need it.
This would go like
class BaseViewController: UIViewController {
// some of the code you might need
func APIHelper() -> API {
let api = API()
return api
}
}
And later:
class ViewControllerThatNeedsAPI : BaseViewController {
// You have it here
}
Another approach that I actually use is to have service/manager for API calls that handles that, and send all the data needed via delegate/NSNotification/completion handler. That way your code will be cleaner and easier to test ( if you practice tests ). If you keep everything in the view controller you will break the SRP. This managers are PONSO - Plain old ns objects. You could use the same way as for view controllers and have some BaseService with API URL, basic stuff that needs to be overriden etc. After that you just implement service and call it when needed - depending on the implementation have some function to reflect data to UI.
How do you (if possible) create a class that anything that references it gets the same object?
So, if I had a LoginClass
and I dont want to create a new instance in each file but rather be able to just do
LoginClass.userID
in any file without first creating an instance of it?
It possible. Use singleton:
Stackoverflow question
Tutorial by Ray Wenderlich
You are looking for a Singleton
This is the code
class Login {
static let sharedInstance = Login()
var userID: String?
private init() {}
}
This is how you retrieve the same instance
Login.sharedInstance
And this is how you use it
Login.sharedInstance.userID = "123"
In a different point of your code...
print(Login.sharedInstance.userID) // 123
Creating one instance per application life cycle means you want to implement Singleton pattern. You can implement singleton like this
class LoginManager {
static let sharedInstance = LoginManager()
var userId:String?
var name:String?
}
And now you can use this like
LoginManager.sharedInstance.userId
I am using Realm and it has function that take as an argument a class inheriting from Object (not NSObject), e.g.
realm.objects(Class)
I want to make a function that also takes Class as parameter.
I want make function that will take a class and forward it to Realm's function. I tried something like this, but it doesn't work:
func test(type: AnyClass) {
let realm = ..
realm.objects(type)
}
The Swift compiler reports an error saying that it cannot cast from AnyClass to Object.Type
I found a similar question here: Pass a Swift class as parameter, and then call a class method out of it
But maybe there is a simpler solution that doesn't require protocol implementation for every class? I want the function to make the decision of what to do by itself depending on what class it receives.
I want it to look like realm.objects(Class).
You can use the same signature: objects declaration looks like this:
func objects<T: Object>(type: T.Type) -> Results<T>
So you need a generic function constraining the type to subclasses of Realm.Object:
func test<T: Object>(type: T.Type) {
let realm = ...
realm.objects(type)
}
Then, assuming that your class (MyClass in this sample) inherits from Realm.Object, you can call it like this:
class MyClass: Object {}
test(MyClass)
If your method takes an object of that type, you can infer the type:
func test<T: Object>(element: T) {
let realm = ...
realm.objects(T.self)
}
I learn the Swift Language and i need to create a manager like a Parse sdk.
For exemple when you initialize your Parse in app you write
Parse.setApplication("...", applicationId:"...")
And later you can write code like this
Parse.doSomething()
The method doSomething() use initial context.
Can you show me in my class should look like? I try some singleton exemple, but a have MyClass.sharedAttribute.doSomething() in case
What you have shown is no indication of singletons whatsoever, it sounds and looks more like a static class with static members and properties:
class MyStatic {
static var appIdA : String?
class func setApplicationId(a : String) {
appIdA = a
}
class func doSomething() {
print(appIdA)
}
}
MyStatic.setApplicationId("blabla")
MyStatic.doSomething() // prints Optional("blabla")
Of course there is the possibility that internally the class is a singleton, but Parse does not seem to be one, just looking at the functions it exposes.
The code comments even state
/*!
The `Parse` class contains static functions that handle global configuration
for the Parse framework.
*/