XCode unit test - xcode

Making CoreData model with simple class Mood:
import Foundation
import CoreData
class Mood: NSManagedObject {
static let entityName = "\(Mood.self)"
class func mood(withTitle title: String) -> Mood {
let mood: Mood = NSEntityDescription.insertNewObject(forEntityName: Mood.entityName, into: CoreDataController.sharedInstance.managedObjectContext) as! Mood
mood.title = title
return mood
}
}
extension Mood {
#NSManaged var title: String
}
and writing simple unit test for that class:
import XCTest
#testable import DiaryApp
class DiaryAppTests: XCTestCase {
var mood = Mood.mood(withTitle: "Happy")
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testExample() {
XCTAssertNotNil(self.mood)
}
}
getting error: "Could not cast value of type 'DiaryApp.Mood' (0x6000000df730) to 'DiaryAppTests.Mood' (0x10e9ed8a8)."
What am I doing wrong?

Solved it by removing all files of my project from DiaryAppTests Compile Sources (at Build Phase tab in TARGETS) - after that my classes were undefined in Tests. For make them defined added string "#testable import DiaryApp" before declaration of TestCase.

Related

How to write getter and setter for HasDelegate protocol in RxSwift?

I am implementing HasDelegate protocol to the IWDeviceManager.
In all the posts which I have read, no one has wrote getter & setter for this public var delegate property.
The compiler is explicitly asking me to write getter & setter for public var delegate. Why it's required in my case?
I tried writing but my code crashes when I try to get or set the delegate.
How do I solve this issue?
I have shared the code below
extension IWDeviceManager: HasDelegate {
public typealias Delegate = IWDeviceManagerDelegate
// Compiler explicitly asks to write getter and setter for this.
public var delegate: IWDeviceManagerDelegate? {
get { // Crashes here
return IWDeviceManager.shared()?.delegate
}
set(newValue) { // crashes here
IWDeviceManager.shared()?.delegate = newValue
}
}
}
Below is interface for IWDeviceManager
open class IWDeviceManager : NSObject {
weak open var delegate: IWDeviceManagerDelegate!
open class func shared() -> Self!
open func initMgr()
open func initMgr(with config: IWDeviceManagerConfig!)
}
Instead of using HasDelegate try this:
class IWDeviceManagerDelegateProxy
: DelegateProxy<IWDeviceManager, IWDeviceManagerDelegate>
, DelegateProxyType
, IWDeviceManagerDelegate {
init(parentObject: IWDeviceManager) {
super.init(parentObject: parentObject, delegateProxy: IWDeviceManagerDelegateProxy.self)
}
static func currentDelegate(for object: IWDeviceManager) -> Delegate? {
return object.delegate
}
static func setCurrentDelegate(_ delegate: IWDeviceManagerDelegate?, to object: IWDeviceManager) {
object.delegate = delegate
}
static func registerKnownImplementations() {
self.register { IWDeviceManagerDelegateProxy(parentObject: $0) }
}
}

OnClick Adapter on Kotlin

My kotlin code brakes when the onclick adapterPosition. I've debug the code but I'm still not sure what is going on and why is not working.
Here is my Category Adapter:
import android.content.Context
import android.content.Intent
import android.support.v7.widget.CardView
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import com.google.android.gms.common.internal.service.Common
import com.letsbuildthatapp.kotlinmessenger.Quizz.Model.Category
import com.letsbuildthatapp.kotlinmessenger.Quizz.Model.Interface.IOnRecyclerViewItemClickListener
import com.letsbuildthatapp.kotlinmessenger.Quizz.Model.Question
import com.letsbuildthatapp.kotlinmessenger.R
class CategoryAdapter(internal var context: Context,
internal var categoryList: List<Category>):
RecyclerView.Adapter<CategoryAdapter.MyViewHolder>() {
//This is correct
override fun onCreateViewHolder(parent: ViewGroup, p1: Int): MyViewHolder {
val itemView = LayoutInflater.from(context).inflate(R.layout.layout_category_item, parent, false)
return MyViewHolder(itemView)
}
// this is correct
override fun getItemCount(): Int {
return categoryList.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.txt_category_name.text = categoryList[position].name
holder.setiOnRecyclerViewItemClickListener(object : IOnRecyclerViewItemClickListener {
override fun onClick(view: View?, position: Int) {
// this is to direct user to the question List
com.letsbuildthatapp.kotlinmessenger.Quizz.Model.Common.Common.selectedCategory = categoryList[position]
val intent = Intent(context, Question::class.java)
context.startActivity(intent)
}
})
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
internal var txt_category_name: TextView
internal var card_category: CardView
internal lateinit var iOnRecyclerViewItemClickListener: IOnRecyclerViewItemClickListener
fun setiOnRecyclerViewItemClickListener(iOnRecyclerViewItemClickListener: IOnRecyclerViewItemClickListener) {
this.iOnRecyclerViewItemClickListener = iOnRecyclerViewItemClickListener
}
init {
txt_category_name = itemView.findViewById(R.id.txt_category_name) as TextView
card_category = itemView.findViewById(R.id.card_category) as CardView
itemView.setOnClickListener(this)
}
override fun onClick(view: View?) {
iOnRecyclerViewItemClickListener.onClick(view, adapterPosition)
}
}
}
Here is the IonRecyclerViewItemClickLister
interface IOnRecyclerViewItemClickListener {
fun onClick(view: View?, position:Int)
}
I've debugged the code and it appears to work well until it reaches to this part:
override fun onClick(view: View?) {
iOnRecyclerViewItemClickListener.onClick(view, adapterPosition)
}
}
}
My question is what am I doing wrong.
Implement your interface in your activity and pass it as parameter to your Adapter. After pass it your view holder.
I'll let you with an example of my project.
My interface
MainActivity - Where I implement the Interface
My adapter
I discovered where the error was
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.txt_category_name.text = categoryList[position].name
holder.setiOnRecyclerViewItemClickListener(object : IOnRecyclerViewItemClickListener {
override fun onClick(view: View?, position: Int) {
// this is to direct user to the question List
com.letsbuildthatapp.kotlinmessenger.Quizz.Model.Common.Common.selectedCategory = categoryList[position]
val intent = Intent(context, Question::class.java)
context.startActivity(intent)
}
})
}
The error was in point to an Activity that doesn't exist.

Can a MPMediaEntityPersistentID be cast to a value which can be saved to NSUserDefaults.standardUserDefaults?

I am trying to save a [MPMediaEntityPersistentID] using NSUserDefaults.standardUserDefaults(); however, I cannot cast the MPMediaEntityPresitstentID to a type which can be saved.
Here is the code:
import Foundation
import AVFoundation
import MediaPlayer
class SaveFileArray
{
var songFileArray = [MPMediaEntityPersistentID]()
init() {
songFileArray = []
}
func saveFile(id: MPMediaEntityPersistentID) {
let songID = id as NSString
songFileArray.append(id)
//Instead of printing lets save the MPMediaEntityPersistentID
print(songFileArray[0])
NSUserDefaults.standardUserDefaults().setObject(songFileArray, forKey: "time")
NSUserDefaults.standardUserDefaults().synchronize()
}
func countSavedFiles() -> Int {
return songFileArray.count
}
}
Question:
Can anyone offer me a solution as to how I can save songID into NSUserDefaults?

Accessing PFObject Subclassed Properties from a Query

I am using Parse and have created a subclass of PFObject. When creating objects it makes things much easier. Once objects are created, I am experimenting with querying the database and accessing the custom properties I created. What I am finding is that I cannot use dot notation to access the properties when I am working the the PFObjects returned from the query. Is this normal?
Here is subclass I created.
import Foundation
import UIKit
import Parse
class MessagePFObject: PFObject
{
#NSManaged var messageSender : String
#NSManaged var messageReceiver : String
#NSManaged var messageMessage : String
#NSManaged var messageSeen : Bool
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Custom Query method.
override class func query() -> PFQuery?
{
let query = PFQuery(className: MessagePFObject.parseClassName())
query.includeKey("user")
query.orderByDescending("createdAt")
return query
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
init(messageSenderInput: String?, messageReceiverInput: String?, messageMessageInput: String?)
{
super.init()
self.messageSender = messageSenderInput!
self.messageReceiver = messageReceiverInput!
self.messageMessage = messageMessageInput!
self.messageSeen = false
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
override init()
{
super.init()
}
}
//++++++++++++++++++++++++++++++++++++ EXTENSION +++++++++++++++++++++++++++++++++++++++++++++++++++
extension MessagePFObject : PFSubclassing
{
class func parseClassName() -> String
{
return "MessagePFObject"
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
override class func initialize()
{
var onceToken: dispatch_once_t = 0
dispatch_once(&onceToken) {
self.registerSubclass()
}
}
}
Here is my query and what I am required to do to access the properties. createdAt, updatedAt, etc are all available with dot notation but none of my custom properties are. You can see I access messageSeen with element.objectForKey("messageSeen").
let predicate = NSPredicate(format: "messageSender == %# OR messageReceiver == %#", self.currentUser!.username!, self.currentUser!.username!)
let query = messagePFObject.queryWithPredicate(predicate)
query!.findObjectsInBackgroundWithBlock ({ (objects, error) -> Void in
if error == nil && objects!.count > 0
{
for element in objects!
{
print(element)
print(element.parseClassName)
print(element.objectId)
print(element.createdAt)
print(element.updatedAt)
print(element.objectForKey("messageSeen"))
}
}
else if error != nil
{
print(error)
}
})
If this is normal then that is fine. I just want to make sure I am not missing something.
Take care,
Jon
Your object subclass has to implement the PFSubclassing protocol and you need to call MessagePFObject.registerSubclass() in your app delegate.
The parse documentation is very good : https://parse.com/docs/ios/guide#objects-subclasses

Changing a JSContext-passed Swift object with JavaScriptCore

I have a problem changing an object passed into JavaScriptCore.
Here is my custom object, defining a single String property called testProperty:
import Foundation
import JavaScriptCore
protocol JSCustomObjectExport: JSExport {
var testProperty: String { get set }
}
class JSCustomObject: NSObject, JSCustomObjectExport {
var testProperty: String = "ABC"
}
Here is the AppDelegate in which I create a JSContext, pass my custom object to it and run a JS script to change its testProperty from "ABC" to "XYZ". However the testProperty is never changed.
import Cocoa
import JavaScriptCore
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet var window: NSWindow!
lazy var context = JSContext()
func applicationDidFinishLaunching(aNotification: NSNotification?) {
println("Started")
var co = JSCustomObject()
context.globalObject.setValue(co, forProperty: "customObject")
context.evaluateScript("customObject.testProperty = 'XYZ'")
println(co.testProperty) // ERROR(?): This prints "ABC" instead of "XYZ"
}
}
Am I doing something wrong? Shouldn't co.testProperty change?
Btw, this is an OS X app, compiled in XCode 6.1.1 on OSX 10.10.1.
It seems, it requires that the protocol is marked as #objc, and the class has explicit #objc export name.
I tried the following script in Playground, and it works
import Foundation
import JavaScriptCore
#objc // <- HERE
protocol JSCustomObjectExport: JSExport {
var testProperty: String { get set }
}
#objc(JSCustomObject) // <- HERE
class JSCustomObject: NSObject, JSCustomObjectExport {
var testProperty: String = "ABC"
}
var context = JSContext()
var co = JSCustomObject()
context.globalObject.setValue(co, forProperty: "customObject")
context.evaluateScript("customObject.testProperty = 'XYZ'")
println(co.testProperty) // -> XYZ

Resources